ArticleCategory: [Choose a category for your article]

AuthorImage:[Here we need a little image from you]

TranslationInfo:[Author and translation history]

AboutTheAuthor:[A small biography about the author]

Computer Science is my profession and also part of my free time. I like
to share my hobby, as everyone probably does. I admit it! I am one of
those strange characters who dislikes windoze, at least MSDOS has the
category of a toy that is least pretentious of its capabilities and
does not fill your computer of numerous files that where you never now
if they are useful and what they are good for.

Abstract:[Here you write a little summary]

This time we explore how to design recursive structures with Povray and
how to create beautiful images with this technique.

ArticleIllustration:[This is the title picture for your
article]

ArticleBody:[The article body]

Art and Tecnique in computer science.

Our series of articles touches technical and non-technical aspects of
POVRAY. Technology is important, we already mentioned it several times,
but it is even more important to learn to take advantage of its
possibilities in an artistic and creative environment. The computer
science is so unlike any other discipline that perhaps for some it
might be the perfect environment to express his or her artistic
qualities. We cannot abandon the process of learning about technology
because it is a necessary step, however in my personal experience
technology is only an instrument that helps us to achieve a new form of
communication.

In my articles I try to mix cold technical knowledge with issues
purely creative or artistic. My goal is to put forward ideas, examples
that can trigger the imagination and perhaps form new paths in the
readers mind. Some times I start the design of a new example and I have
so much fun that the issues I wanted to explore become hidden and
forgotten. A purely systematic presentation becomes boring and
therefore not very pedagogic.

The manual for Povray was develop as a systematic presentation of
various technical issues. It is a great reference guide and I use it
very often. In contrast to that sequential and systematic approach we
will follow more of an spiral approach, coming back to the same issues
many times and each time in greater depth.

The scenes presented as examples in our series hope to provide not
only an illustration to the technical issue at hand but also some
aesthetic example of how that particular technique could be used to
produce beautiful results. This goal may require on occasions to
introduce new and foreign elements of POVRAY not yet discussed in the
series. Please do not worry if you do not understand everything yet,
step by step we will cover every issue in the examples. On the other
hand many techniques used are so visual in nature that they hardly
require a written explanation because just "seeing" the result of the
example is worth more than a lengthy explanation. Those who really wish
to advance faster learning Povray can always go to the reference
manual.

Simple Geometrical Objects

Most of these objects have been already used in previous examples. Let
us review them now to bring all this information together.

The number of objects that can be designed based on the following
series of simple geometrical objects is countless, thus reducing
objects to an ensemble of elemental forms represents a considerable
savings of time processing the scene. Here is our list:

The spheresyntax: sphere { < x, y, z>, radius ... }
where x, y, z are the coordinates of the center. After the radius may
follow additional statements to specify other characteristics like
scale, rotation, translation, texture, color, etc...

The conesyntax: cone { <x1, y1, z1>, rad1 <x2, y2, z2>, rad2
[open] ..... }
This statement let us specify a conical section, x1, y1, z1 are the
coordinates of the cone center on one extreme and r1 the radius at the
section and x2, y2, z2 and r2 are the center coordinates and radius on
the other extreme. Two make a true cone just make one of the radius
equal to zero. Another optional parameter is the token "open", when
present it renders an open cone, if not present the cone is close.

The Cylindersyntax:cylinder { <x1, y1, z1>, <x2, y2, z2>, rad
[open] ...... }
where x1, y1, z1 and x2, y2, z2 are the coordinates of the center of
th cylinder at both ends. As before rad is the radius across the
section of the cylinder and the token "open" is an optional parameter
that selects an open or close (if not present) cylinder.

The Planesyntax:plane { <x, y, z>, dist ..... }
This time x, y and z do not represent the coordinates of a point but a
vector perpendicular to the surface of the plane. The value dist is the
distance from the center of coordinates to the plane. Remember Povray
allows abbreviation of vectors as in x = <0, 1 , 0> -z = <0, 0,
-1>. Sometimes a plane can be represented using a sphere with a very
large radius; in fact we used this technique in a previous
article.

Constraint Solid Graphics(CSG)

CGS primitives are elementary solid objects that can be combined into
more complex models. The final combination can be grouped and
transformed using scaling, translations, rotations transformations or
filling in textures, etc... It is not necessary to to apply each of
these transformations to each and everyone of the elementary primitives
in the combined model.

There are four methods to combine CGS primitives, and there is a
fifth complement method that applies to single primitives:

Union
'union { object {A} object{B} }'
All the points in the combined object belong to A OR B

Intersection
'intersection { object {A} object {B} }'
All the points in the combined object belong to A and B

Inverse
object {A inverse}
All the points in the combined object do not belong to A

Difference
'difference { object {A} object {B} }'
All the points in the combined object belong to A but not to B,
in other terms 'union { object {A} object {B inverse }'

Merge
'merge { object {A} object {B} }'

As in the union, except that the internal surfaces of A and B are
removed. If the objects are not translucid this features is of no
use.

In the following examples we will use several of these operations to
build solid models. I recommend to build models by adding first all the
elements needed to make the overall volume and then using intersection
operations to eliminate the undesired parts.

When primitives objects in a solid model have common surfaces there
may be problems of rendering points in one of the other surface due to
machine precission. This problem can be worked around by introducing a
very small translation in one the objects to clearly distinguish to
which object the surface belongs to.

Loops and Conditionals in Povray.

The elements in a scene are described generally in an arbitrary
order. Nevertheless there are occasions when it is very convenient to
implement procedural loops to create iterative structures, for example.
Loops can be implemented in Povray using several methods. One method is
the loop flow control directive provided by the language itself.

The loop flow control is just one of many directives of the POVRAY
programming interface. Some while ago we mentioned other directives
like #declare and #include and we characterized many others as of minor
importance. The example that follows was edited directly in POVRAY and
I must confess this is the first time I use the loop flow control
directive. The reason is that often it is possible to achieve the same
result by generating the POVRAY source with a separate program (C or
C++) that has loop flow control statements (for loop). We will see at
some point an example of this technique.

The reader with C experience will understand that Povray's
programming interface is not as elegant as other general purpose
programming languages (C, C++). This should not come as a surprise
because POVRAY was designed as a language for the description of
scenes, and the flow control directives were later additions. Similarly,
POVRAY includes directives for performing complex mathematical
operations and all kind of loops. Personally I believe it is fantastic
that POVRAY includes all these operations, on the other hand they are
not really not absolutely necessary since we can alway execute them externally in
more powerful programming languages. I do not see how performing these
operations externally or internally makes any difference to the final
artistic value of the composition. For me the most important issue is
the quality of the final image. To a lesser extent it should also be a
factor the time and effort required to develop and process the image.
Users more familiar with general purpose languages may feel better
generating POVRAY files through them, others without programming
experience perhaps would feel more comfortable writing directly in
POVRAY. Also for simple images direct editing in POVRAY is easier while
for complex scenes the generation of POVRAY files by other programs may
be better. We will explore both methods and let the reader pick
accordingly.

Using the Trial and Error Method

Many scenes can be designed starting from a simple idea. After a
first implementation we may decide to change some value or use
approximations to achieve a better result. So trial and error is an
integral part of scene design in POVRAY. At the beginning of this
series of articles we offered readers a simple script-tool (POV) to
facilitate the generation of images, but the reader should not think
that this little script is sufficient. Often times you will need plain
paper, pencil and a calculator. In many occasions there is no choice
because our designs involved 3D geometries, some knowledge of special
geometry and trigonometry are fundamental in order to achieve certain
effects. Generally it is sufficient to know a few formulas, so let us
remember some basic trigonometric relationships:

Next as a reminder we will tabulate the main domains for the
trigonometric functions as a function of the quadrant:

Quadrant

Sine

Cosine

Tangent

0 .. 90

0 .. +1

+1 .. 0

0 .. +Infinity

90 .. 180

+1 .. 0

0 .. -1

-Infinity .. 0

180 .. 270

0 .. -1

-1 .. 0

0 .. +Infinity

270 .. 360

-1 .. 0

0 .. +1

-Infinity .. 0

a = atan(A/B)

This last relationship is not uniquely defined. The angle alpha is
undetermined by +/- 180 degrees.Computationally it is preferably to use
this:

a = atan2(A,B)

Finally the distance from P1(x1,y1,z1) to P2(x2,y2,z2) is

D = sqrt( (x2-x1)^2 + (y2-y1)^2 + (z2-z1)^2 )

There are many usefull trigonometric relationships but the ones
already reviewed should be sufficient for most cases. The implicit
trigonometric functions implemented in POVRAY assume by default angles
in radians. The conversion function radians(alpha) transforms
degrees to radians. Unfortunately POVRAY is not consistent, for example
rotations are measured in degrees! :-(

Sea-urchins

In the following example we use some very basic trigonometry. The
spikes in the sea-urchin are placed very conveniently, and this effect
cannot be easily achieved by chance. The designer has to think about an
algorithm to place the spikes exactly and implement it with a clear
idea of the final 3D configuration. The source code for the example is
sufficiently documented, so it is not worth to make further comments
here. This example is a clear case where a loop algorithm applies.
Whether the designer decides to implement the loop within POVRAY or
outside via a C-program is a matter of personal choice.

Here are the sources for the fish. They are modeled using CGS
primitives as previously described.

Next comes the sources for the remaining scene. The most
peculiar issue here is the definition of the sea-urchin (erizo in
Spanish) that without a doubt are the principal characters in the
composition:

A number of effects in this example are completely new, for example
the surface effects on the sand (waves on the sand), the atmospheric
effects (a fog of green marine color very thick and very humid) and the
complex CGS objects as well. The light in the scene comes from many
point sources disperse over the medium to simulate the underwater
illumination, characterized by the disorder scattering from the waves
on the surface. A single light source would be inappropriate for this
composition because it would the shadow of the sea-urchin would be too
sharp.

Generation by External Programs.

A ray-tracer is merely a tool to generate a complete scene specified
with the help of a formal ray-tracing language. Ray-traces are able to
understand color and light specifications, etc... Often times there is
previous work to support our design work: 3D scanners, format
conversion tools, programs, among others. Therefore a ray-tracer is
just one in a chain of of tools for scene construction and design. In
other words, design by typing on the keyboard our ideas is not the only
mechanism for producing artistic compositions, we have auxiliary tools
to produce more complex compositions that are not so easily type by
hand in a ray-tracer language.

As an example of a complex scene generated by an external program we
will next provide a C-program names burbujas.c (bubbles). The program
places a number of bubbles at random on a surface of size 1000x750
pixels. Bubbles cannot intersect amongst themselves, so our example
code determines random positions and random sizes accordingly. If the
new location generated by for a bubble falls near an existing bubble a
new position is then computed. The size of the sphere is reduced to
make them fit. After a large number of iterations one obtains a surface
with almost no free space left. The generation of this particular
example requires a lot of computation because as the sequence
progresses in becomes harder and harder to fit a new bubble.

Compile and run this program. Redirect the standard output to a file
name 'burbujas.inc' where the data for the bubbles remain stored
(burbujas > burbujas.inc). The output file contains entries as
these:

I recommend some patience because it takes a while to generate the
output file. At any moment you can interrupt the process and edit the
output file to make sure that the last entry line is complete. If not
just remove it from the file. The source for pov will the
following:

The source code contains again references to the token "clock" but
this time its purpose is very different. In this case it does not
generate a sequence of images for an animation but four images with
very different points of view. The position, angle and aperture of the
camera varies among the four images.

In the previous POVRAY article we already mentioned that at some
point we would examine examples that explore the possibilities of the
camera in POVRAY. Well this is one example. It is quite obvious the
differences on the final rendered image according to the specifications
of the camera. One can achieve many perspectives according to the angle
of aperture: small angle yields far perspectives while wide angles
yield close-ups. The maximum angle is 180 degrees, it is a very extreme
value because it is hard to distinguish shapes.

The images shown were processed on a Pentium 200 MMX 48MB Ram (398
bogomips). It was executed as suggested by using the tool provided
earlier in the series, 'pov':

pov burbujas 6 9 1 5 1 5
Total Time =

The parameter passed represent:

Source file is burbujas.pov

Size 6 = (400x300)

Quality 9

Initial photogram = 1

Final photogram = 5

Initial clock = 1

Final clock = 5

The time spend to generate each photogram is considerable. With
better quality it would take the following times:

Let us examine now the results. In the first of the four photograms
the only variation is the camera setup. (position, angle, orientation,
etc)

Before showing the last photogram let me go over another issue that
is relevant to appreciate this last image, the issue of CPU
optimization.

CPU Usage Optimization

The last photogram is the most complex and POVRAY was not able to
optimize it. When confronted by complex compositions the ray-tracer
tries to simplify the scene to the simplest common denominator. In
previous versions of POVRAY the optimizations had to be done by hand;
to this end artists had the directive 'bounded_by' to specify a
primitive that would wrap one or more objects. Then the ray-tracer
assumed that rays that did not collide with this wrapping would not
collide either with any of the objects inside. This is an approximation
that saves some processing time. There are very few cases where it is
actually useful. As it turns out, our last image is one of those
cases!. The last image contains to many objects and is very complex.
Therefore it would have been better to manually optimize the
composition, for example by grouping bubbles by zones, joining bubbles
into compound objects, or even combining all the bubbles in one object
but wrapping groups of spheres within the same region using the command
'bounde_by'. The syntax would be:

The type of manual optimization described can be used with unions
and intersections and also with any other object. The user may also
select other wrapping primitives, we chose a sphere, however the best
results are often obtained with boxes and spheres. If the primitive
selected leaves part of the compound object outside the result can be
defective.

Once again I would like to stress that the need for manual
optimizations is rare. Our last example was conceived with 'bad
intentions' beforehand in order to raise the issue. POVRAY automatic
optimizer was unable to handle any better the composition. It contains
2154 spheres. The reader could check it out counting them :-).

In our example we have shown how to play with the possibilities of
the ray-tracer. Many times the same idea or concept can be implemented
in various ways to obtain diverse results and here is where the
artist's creativity surfaces.

What is missing...

Povray provides many mathematical functions, some more or less
interesting. Unfortunately there is one very interesting function
missing. It is the "spline". There is nothing as convenient as tracing
with pencil and paper a few points and then applying a function that
draws a smooth line across the points. Povray's spline primitive can
not be used as a function, instead it generates a line as the basis for
building other forms, it would be better if we could apply the spline
to any variables we wish. That would allow for example to make the
camera follow an arbitrary trajectory. I would also be great if one
could implement external functions. To some degree all these can be
achieve by using includes and external programming. Under Linux we have
a utility named 'spline'. It can be used as a command to generate the
desired curve from a set of points. Try to combine this command with
external programming, for example to generate animations or camera
movement.

Exercises

Optimize of the last photogram following the recommendations just
given.

Translate the program burbujas.c to POVRAY language.

Translate the program erizos.c to a general purpose language.

Reader contributions

I am eager to here from readers and see their compositions, perhaps
employing the recursive or loop structures discussed here. Please send
me you experiments in compress files. It would be great to collect
readers collaborations and organize an exhibition here in the
LinuxFocus magazine. I will select the most interesting or imaginative
images for the exhibition. Please do not submit images under some kind
of commercial for-pay license. If possible send also the sources for
the images so that other people can learn from your ideas.

References

The version of povray used for this article was version 3.1g This
version was at time of writing the current version available from
www.povray.org. You can as well download them form the _LF_ server: pre-compiled:
povlinux.tgz (1.4Mb), unix sources:
povuni_s.tgz (960Kb).