|
A torus
can be thought of as a donut or an inner-tube. It is
a shape that is vastly useful in many kinds of CSG so POV-Ray has adopted
this 4th order quartic polynomial as a primitive shape. The syntax for a
torus is so simple that it makes it a very easy shape to work with once we
learn what the two float values mean. Instead of a lecture on the subject,
let's create one and do some experiments with it.
We create a file called tordemo.pov
and edit it as follows:
#include "colors.inc" camera { location <0, .1, -25> look_at 0 angle 30 } background { color Gray50 } // to make the torus easy to see light_source { <300, 300, -1000> White } torus { 4, 1 // major and minor radius rotate -90*x // so we can see it from the top pigment { Green } }
We trace the scene. Well, it's a donut alright. Let's try changing the major and minor radius values and see what happens. We change them as follows:
torus { 5, .25 // major and minor radius
That looks more like a hula-hoop! Let's try this:
torus { 3.5, 2.5 // major and minor radius
Whoa! A donut with a serious weight problem!
With such a simple syntax, there isn't much else we can do to a torus besides change its texture... or is there? Let's see...
Tori are very useful objects in CSG. Let's try a little experiment. We make a difference of a torus and a box:
difference { torus { 4, 1 rotate x*-90 // so we can see it from the top } box { <-5, -5, -1>, <5, 0, 1> } pigment { Green } }
Interesting... a half-torus. Now we add another one flipped the other way. Only, let's declare the original half-torus and the necessary transformations so we can use them again:
#declare Half_Torus = difference { torus { 4, 1 rotate -90*x // so we can see it from the top } box { <-5, -5, -1>, <5, 0, 1> } pigment { Green } } #declare Flip_It_Over = 180*x; #declare Torus_Translate = 8; // twice the major radius
Now we create a union of two Half_Torus
objects:
union { object { Half_Torus } object { Half_Torus rotate Flip_It_Over translate Torus_Translate*x } }
This makes an S-shaped object, but we can't see the whole thing from our present camera. Let's add a few more links, three in each direction, move the object along the +z-direction and rotate it about the +y-axis so we can see more of it. We also notice that there appears to be a small gap where the half Tori meet. This is due to the fact that we are viewing this scene from directly on the x-z-plane. We will change the camera's y-coordinate from 0 to 0.1 to eliminate this.
union { object { Half_Torus } object { Half_Torus rotate Flip_It_Over translate x*Torus_Translate } object { Half_Torus translate x*Torus_Translate*2 } object { Half_Torus rotate Flip_It_Over translate x*Torus_Translate*3 } object { Half_Torus rotate Flip_It_Over translate -x*Torus_Translate } object { Half_Torus translate -x*Torus_Translate*2 } object { Half_Torus rotate Flip_It_Over translate -x*Torus_Translate*3 } object { Half_Torus translate -x*Torus_Translate*4 } rotate y*45 translate z*20 }
Rendering this we see a cool, undulating, snake-like something-or-other. Neato. But we want to model something useful, something that we might see in real life. How about a chain?
Thinking about it for a moment, we realize that a single link of a chain can
be easily modeled using two half tori and two cylinders. We create a new
file. We can use the same camera, background, light source and declared
objects and transformations as we used in tordemo.pov
:
#include "colors.inc" camera { location <0, .1, -25> look_at 0 angle 30 } background { color Gray50 } light_source{ <300, 300, -1000> White } #declare Half_Torus = difference { torus { 4,1 sturm rotate x*-90 // so we can see it from the top } box { <-5, -5, -1>, <5, 0, 1> } pigment { Green } } #declare Flip_It_Over = x*180; #declare Torus_Translate = 8;
Now, we make a complete torus of two half tori:
union { object { Half_Torus } object { Half_Torus rotate Flip_It_Over } }
This may seem like a wasteful way to make a complete torus, but we are really going to move each half apart to make room for the cylinders. First, we add the declared cylinder before the union:
#declare Chain_Segment = cylinder { <0, 4, 0>, <0, -4, 0>, 1 pigment { Green } }
We then add two Chain_Segments
to the union and translate
them so that they line up with the minor radius of the torus on each
side:
union { object { Half_Torus } object { Half_Torus rotate Flip_It_Over } object { Chain_Segment translate x*Torus_Translate/2 } object { Chain_Segment translate -x*Torus_Translate/2 } }
Now we translate the two half tori +y and -y so that the clipped ends meet
the ends of the cylinders. This distance is equal to half of the previously
declared Torus_Translate
:
union { object { Half_Torus translate y*Torus_Translate/2 } object { Half_Torus rotate Flip_It_Over translate -y*Torus_Translate/2 } object { Chain_Segment translate x*Torus_Translate/2 } object { Chain_Segment translate -x*Torus_Translate/2 } }
We render this and voila! A single link of a chain. But we aren't done yet! Whoever heard of a green chain? We would rather use a nice metallic color instead. First, we remove any pigment blocks in the declared tori and cylinders. Then we add a declaration for a golden texture just before the union that creates the link. Finally, we add the texture to the union and declare it as a single link:
#declare Half_Torus = difference { torus { 4,1 sturm rotate x*-90 // so we can see it from the top } box { <-5, -5, -1>, <5, 0, 1> } } #declare Chain_Segment = cylinder { <0, 4, 0>, <0, -4, 0>, 1 } #declare Chain_Gold = texture { pigment { BrightGold } finish { ambient .1 diffuse .4 reflection .25 specular 1 metallic } } #declare Link = union { object { Half_Torus translate y*Torus_Translate/2 } object { Half_Torus rotate Flip_It_Over translate -y*Torus_Translate/2 } object { Chain_Segment translate x*Torus_Translate/2 } object { Chain_Segment translate -x*Torus_Translate/2 } texture { Chain_Gold } }
Now we make a union of two links. The second one will have to be
translated +y so that its inner wall just meets the inner wall of the other
link, just like the links of a chain. This distance turns out to be double
the previously declared Torus_Translate
minus 2 (twice the minor
radius). This can be described by the expression:
Torus_Translate*2-2*y
We declare this expression as follows:
#declare Link_Translate = Torus_Translate*2-2*y;
In the object block, we will use this declared value so that we can
multiply it to create other links. Now, we rotate the second link
90*y
so that it is perpendicular to the first, just like links of a
chain. Finally, we scale the union by 1/4 so that we can see the whole
thing:
union { object { Link } object { Link translate y*Link_Translate rotate y*90 } scale .25 }
We render this and we will see a very realistic pair of links. If we want to make an entire chain, we must declare the above union and then create another union of this declared object. We must be sure to remove the scaling from the declared object:
#declare Link_Pair = union { object { Link } object { Link translate y*Link_Translate rotate y*90 } }
Now we declare our chain:
#declare Chain = union { object { Link_Pair} object { Link_Pair translate y*Link_Translate*2 } object { Link_Pair translate y*Link_Translate*4 } object { Link_Pair translate y*Link_Translate*6 } object { Link_Pair translate -y*Link_Translate*2 } object { Link_Pair translate -y*Link_Translate*4 } object { Link_Pair translate -y*Link_Translate*6 } }
And finally we create our chain with a couple of transformations to make it easier to see. These include scaling it down by a factor of 1/10, and rotating it so that we can clearly see each link:
object { Chain scale .1 rotate <0, 45, -45> }
We render this and we should see a very realistic gold chain stretched diagonally across the screen.
|