Sunday, December 23, 2012

Juggling with mutual recursion

Mutually recursive functions are not idiomatic in C, and can easily be avoided. However, they can be fun to play with. 

int f(int);
int g(int);

int f(int j)
{
   if (j > 0)
      return g(j-1);
   return 0;
}

int g(int j)
{
   if (j > 0)
      return f(j-2);
   return -1;
}

int main()
{
   return f(5);
}


Nothing remarkable here. The following, in contrast, doesn't work (at least not as expected).

int f(int j)
{
   if (j > 0)
      return g(j-1) - 2;   /* subtraction of -2 ignored */
}


As a proof of concept, here's a 2-D map which is iterated for as long as its coordinates stay in the first quadrant. In fact, the mutual recursion is here used for two alterating maps. It may appear that something strange such as this happens:

Actually, it's simpler:


void s(float x, float y);
void t(float x, float y);


void s(float x, float y)
{
   printf("s(%.5f, %.5f)\n", x, y);
   if(x >= 0.0 && y >= 0.0)
      
return t(x - 0.5, 1.2*y - .2*x);
}
void t(float x, float y)
{
   printf("t(%.5f, %.5f)\n", x, y);
  
if(x >= 0.0 && y >= 0.0)
      return s(1.2*x - .2*y, y-0.5);
}



This pair of functions differ by not using a return value as part of the recursion. Strange as it looks, it works.


Wednesday, December 5, 2012

Animation tutorial


Computer animation in C++ made easy.


Step 1. Write a sequence of frames to separate image files.
Step 2. Concatenate the frames into a video file.

No, there's no audio here.


For the first step, it is convenient to use a library such as pngwriter that takes care of storing the image in the correct file format  (however, this is neither the most flexible nor the most efficient solution). The frames should be named with an increasing series of numbers, e.g. img001.png, img002.png, img003.png and so on.

Then the frames can be converted to video using ffmpeg. Supposing the images reside in the folder imgfolder, a command like

ffmpeg -f image2 -r 25 -i imgfolder/img_%2d.png animfilm.avi

should do it. There are many other parameters to set, some of which need to be tweaked in order to obtain an acceptable quality. For the C++ program that generates the frames, the main loop may look somewhat as follows. (Note that these lines of code generate something slightly different than the video example above.)


int main()
{
const int W=720, H=576;
pngwriter pict(W, H, 0.0, "imgfolder/img.png");
char fname[32];
int i=0;
const int N = 100;
while(i++ < N)
 {
 float t = (float) i/N;
 pict.line(0, 2*N-i, W, 2*N-i/2, 0.5, 0.5, t);
 sprintf(fname, "imgfolder/img%03d.png", i);
 pict.pngwriter_rename(fname);
 pict.write_png();
}
pict.close();
}



To add audio to all of this (but why should you want to?), mux the video file with an audio file in ffmpeg.





ffmpeg -i soundfile.ogg -i animation.avi -acodec copy -vcodec copy muxedfilm.avi



Following all these steps, you have disqualified yourself to contribute to the monochrome video contest (black only, and no sound track).

Sunday, December 2, 2012