CPSC 324, Spring 2004
Lab 13, Option 2: More About POV-Ray


FOR THE LAST TWO LABS of this course, there is no out-of-class assignment. You will receive six points for showing up and completing the required parts of the lab. Outside of class, you should be working on your final project. You can add a page for the lab to your web site, but that is not required. (Of course, it might help with your final Web site grade.)

For Lab 13, you have two options: Option 1, described on another page, deals with Blender. Option 2, described on this page, deals with POV-Ray. You can do either option.

The POV-Ray option covers a few more features of POV-Ray, which was first introduced in Lab 6. That lab covered basic shapes and textures. This lab looks briefly at programming in POV-Ray, at building objects with Constructive Solid Geometry, and at animation. In the course of the lab, you will create an image something like this one:

POV image

I will also show you how to make an animation that shows the "lens" in this image moving from left to right. To see my animation, change to the directory /home/cs324/lab13_pov and give the command

            animate *.jpg

The directory contains the 100 frames of the animation as separate images. I haven't found a way to put them together into a single animation file, but the animate command can play a sequence of image files as an animation. The animation will run slowly the first time, as the images are loaded, then it will speed up. (Right-click on the window to get a set of menus where you can control the speed.)

Your POV input file will have to include a camera, some lights, and probably a sky. You can start with the following code, which can also be found in the file /home/cs324/lab13_pov/lens.pov. You can copy that file into your account or cut-and-paste the text from this Web page. All the POV-Ray code covered on this page should be added to this file.

            #include "colors.inc"
            #include "textures.inc"

            camera {
              location <2, 6, -15>
              look_at  <0, 1,  0>
            }

            light_source { <5, 18, -15>
              color White
              parallel
            }

            light_source { <-2, 20, 10>
              color White
              parallel
            }

            sky_sphere {
              pigment {
                Bright_Blue_Sky
              }
            }

The /home/cs324/lab13_pov directory also contains a copy of the starter.pov file that you used in Lab 6. You can consult this file for information about POV-Ray shapes and textures if you want a refresher.

Remember that to render an anti-aliased image from lens.pov, you should use the command:

            povray  +A  lens.pov

If you want a 640-by-480 image, and if you want to see the image in the process of being created, you have to add some additional options:

            povray  +A  +D  +W640  +H480  lens.pov

To complete this lab, you must complete the tasks labeled Step 0, Step 1, etc.

Step 0 is to start with a file containing the code given above, and make sure that you know how to render it. You will want to try rendering your scene every time you change this file.


Variables and Control Structures

The POV-Ray scene description language includes some of the capabilities of programming languages. You can define variables and modify their values, and you can use control structures such as if statements and while loops. The syntax, however, is not quite what you are used to.

Variables must be created and assigned an initial value with a #declare statement. For example:

            #declare size = 1;

Rather confusingly, perhaps, #declare is also used to change the value of variable that already exists:

            #declare size = size + 1;

Note that the semicolons at the ends of these statements are required, and that POV-Ray does not have a "+=" operator. Once a variable exists and has a numeric value, it can be used anywhere that a number could be used. For example:

            box {
               <0,0,0>             // One corner of the box
               <size,size,size>    // The opposite corner
               texture {
                  Gold_Metal
               }
            }

(The value of a variable doesn't have to be a number. it can also be a vector or an object. However, I will not use that capability here.)

POV-Ray has control structures that start with #while, #if, and #switch. Note that the statements inside these control structures can include specifications of graphical objects. An if statement, for example, could be used to decide between drawing a sphere and drawing a box. We'll look at the POV-Ray version of while loops here. The while loop has the syntax: #while (<test>) <statements> #end

Step 1: Use a while loop to draw a semicircle of cylinders (or of a different shape if you prefer). A single cylinder can be drawn as follows, where deg is a variable:

       cylinder {
          <0,-5,8>  // Center of one end.
          <0,5,8>   // Center of the other end.
          0.5       // Radius
          texture {
             Polished_Chrome
          }
          rotate <0,deg,0>  // Rotate deg degrees about the y-axis.
       }

You want to draw a cylinder for values of deg between -90 and 90. Use a #while and some #declares to do this. Increment deg by 15 each time through the loop.


Constructive Solid Geometry

Constructive Solid Geometry (CSG) refers to constructing solid objects by applying set operations such as union, intersection, and difference to several objects. If you apply difference to objects X and Y, the result consists of X with any parts that are common to X and Y removed. That is, you remove from X any regions where X intersects Y. For example, your could subtract one cylinder from another to make a hollow tube. Here is how you would do something similar with boxes in POV-Ray:

         difference {
            box {              // A 6-by-6-by-6 cube.
               <-3,-3,-3>
               <3,3,3>
            }
            box {
               <-2.5,-4,-2.5>  // A smaller, but longer 5-by-8-by-5 box.
               <2.5,4,2.5>
            }
            texture {
               White_Marble scale 2
            }
         }

You just list the objects to which you want to apply the difference operation. Note that after the objects, you can include things like textures and transformations that apply to the difference object. You can also list more than two objects in the difference. In that case, objects number 2, 3, etc., are subtracted from object number 1.

Step 2: Subtract three boxes from a cube, leaving just the edges of the cube, as shown in the cubical object in my image. This is the same as the above code that subtracts one box from a cube; you just have to subtract two more boxes.

The union or intersection of two or more objects can done similarly in POV-Ray, using the union or intersection key word. For example, here is how I made the lens object in my image:

           intersection {
              sphere {
                 <0,0,-3>
                 3.5
              }
              sphere {
                 <0,0,3>
                 3.5
              }
              texture {
                 NBglass
              }
              interior {
                 ior 1.5
              }
              translate <0, 2, -6>
           }

The lens is an intersection of two spheres that just slightly overlap. The "interior" specification is necessary to make the lens refractive; without it, the lens is transparent but does not bend light the way real glass would. The lens is created centered at the origin; the "translate" move it 2 units up and 6 units forward.

Step 3: Add the lens object to your scene.

Step 4: Add another object, inside the cube, like the red glass sphere in my image.


Animation in POV-Ray

POV-Ray can do animations, although they are not particularly easy to set up. Animation is entirely based on a predefined variable named clock. You can use this variable in your scene anyplace where you would ordinarily use a number. If you don't do anything else, the value of clock will be zero. However, it is possible to give a different value to clock by using the +K option on the command line. The value of this option becomes the value of clock in the file.

Step 5: In the definition of the lens object, change the line "translate <0, 2, -6>" to "translate <(-5+clock*10), 2, -6>". Then render your scene with the command

            povray  +A  +D  +W640  +H480  +K0.8 lens.pov

You should see that the lens is now in a new position. Different values for the clock variable give different translations.

The whole idea behind animation is to make a sequence of images using different values for clock. By convention, the value of clock starts at 0.0 at the beginning of the animation and finishes at 1.0 at the end. This value can be scaled for different uses in the file, as in the formula (-5+clock*10), which will vary from -5 to 5 as clock varies from 0.0 to 1.0. To make things easy, POV-Ray will do all the frames with one command. You just have to tell it how many frames you want with the +KFF command.

Step 6: Render a 10-frame animation of your scene with the command

            povray  +A  +KFF10  lens.pov

This will produce files named "lens00.png", "lens01.png", ..., "lens10.png". You can play the very short animation with the command "animate *.png". If you want to save space by converting your images to JPEG format, and if you know a bit of advanced shell scripting, you could convert all the files at once with the command:

            for i in `ls lens*.png` ; do  convert $i ${i%%png}jpg ; done

(and then remove the .png files).

If you try to make an animation with more frames, you might find that the program quits abruptly after using ten minutes of processing time. This is because a ten-minute CPU limit has been applied to your account. This is to protect us all from runaway programs. However, you can remove the limit with the command

            ulimit  -t  unlimited

This command only applies to programs that are run from the same command line where you issue the command, so if you want to make a long animation, you should give this command and then run povray in the same window.

If you have additional time in lab, you can try adding different animation to your scene. Make the cube rotate or the cylinders grow, for example.


David Eck