Email: nexusmail at this Web site address
Registration is entirely optional; it's no longer required for posting comments. If you wish to create an account, you may do so
through the login page.
The Astronomy Nexusscience, art, and advice |
|
AboutEmail: nexusmail at this Web site address Registration is entirely optional; it's no longer required for posting comments. If you wish to create an account, you may do so POV-Ray 3.0 For Technical IllustrationStellar CartographyObserving GuidesPersonal ExperiencesOther interests |
More advanced features
Submitted by David on Wed, 2006-04-05 03:08.
CSG: how to make complex objectsConstructive Solid Geometry, or CSG, is an extremely powerful way to make objects that can't easily be represented by the simple objects we've discussed so far (like box, sphere, etc.). There are four basic CSG operations: union, merge, difference, and intersection. The union statement
Objects linked with
#include "colors.inc"
#include "textures.inc"
#include "finish.inc"
camera {location <1,1,-6> look_at <0,0,0>}
light_source {<0,0,-50> color White}
plane {y, -1 pigment {checker color Red, White}}
#declare SimpleSphere = sphere {<0,0,0>, 0.5 pigment {color Red}}
#declare Cluster = union {
object {SimpleSphere}
object {SimpleSphere translate <1,0,1>}
object {SimpleSphere translate <0,1,2>}
object {SimpleSphere translate <1,1,3>}
}
object {Cluster}
The cluster of spheres looks like this:
Now, change the last line to:
object {Cluster translate <-2,0,-0.5>}
and see what happens:
Nice! The whole group of spheres moves on your command. It's possible to change the color or entire texture of a union. There's only one requirement: to apply a single texture (or color, finish, etc.) to an entire union, make sure the objects in the union don't have one already. If the SimpleSphere object didn't already have a red color, you could change the color of the whole union like this:
#declare SimpleSphere = sphere {<0,0,0>, 0.5}
#declare Cluster = union {
object {SimpleSphere}
object {SimpleSphere translate <1,0,1>}
object {SimpleSphere translate <0,1,2>}
object {SimpleSphere translate <1,1,3>}
}
object {Cluster pigment {White_Marble} translate <-2,0,-0.5>}
The merge statement
#include "colors.inc"
#include "textures.inc"
#include "finish.inc"
camera {location <0,1,-4> look_at <0,0.4,0>}
light_source {<0,40,-20> color White}
plane {y, -4 pigment {color White} finish {Dull}}
#declare SimpleSphere1 = sphere {<0,0,0>, 0.5
pigment {color rgbf <1,1,1,1>}
finish {Glass_Finish}}
#declare SimpleSphere2 = sphere {<0,0,0>, 0.5
pigment {color rgbf <1,0.5,0.5,1>}
finish {Glass_Finish}}
#declare Pair1 = union {
object {SimpleSphere1}
object {SimpleSphere2 translate <0.35,0.,0>}
}
#declare Pair2 = merge {
object {SimpleSphere1}
object {SimpleSphere2 translate <0.35,0,0>}
}
object {Pair1 translate <-1,0,0>}
object {Pair2 translate <1,0,0>}
Here, we've defined two spheres, the first colorless (rgb 1,1,1), and the second reddish (rgb 1,0.5,0.5). We'll declare one pair to be a
You can see that in the The difference statementUse the
difference {
object {Original}
object {Cutting Object 1....}
object {Cutting Object 2....}
...
}
i.e., specify the object to be "cut into" first, and then all the other objects that will affect it. A simple example: a cone sliced by a box rotated at an angle:
#include "colors.inc"
#include "textures.inc"
#include "finish.inc"
camera {location <2,2,-6> look_at <0,0,0>}
light_source {<0,40,-20> color White}
plane {y, 0 pigment {color White} finish {Dull}}
#declare SimpleCone = cone {<0,0,0>, 1, <0,2,0>, 0
pigment {color Red}
finish {Dull}}
#declare TurnedBox = box {<-1,-1,-1>, <1,1,1>
pigment {color Blue}
finish {Dull}
rotate 45*z
translate <1,1.75,0>
}
#declare ChoppedCone = difference {
object {SimpleCone}
object {TurnedBox}
}
object {ChoppedCone}
which looks like this:
Note that any new surfaces formed by the "chopping" object take its texture. Again, this is one of those apparent nuisances that's really useful a lot of the time. For example, you can make a telescope mirror by taking a cylinder and then using it in a The intersection statement
#include "colors.inc"
#include "textures.inc"
#include "finish.inc"
camera {location <0,1,-4> look_at <0,0.4,0>}
light_source {<0,40,-20> color White}
plane {y, -4 pigment {color White} finish {Dull}}
#declare Pair1 = union {
object {SimpleSphere1}
object {SimpleSphere2 translate <0.35,0,0>}
}
#declare Pair2 = intersection {
object {SimpleSphere1}
object {SimpleSphere2 translate <0.35,0,0>}
}
object {Pair1 translate <-1,0,0>}
object {Pair2 translate <1,0,0>}
The parts of the spheres that overlap in the Another way to look at it: A problem with CSGWhen the surfaces of two objects coincide exactly, POV-Ray sometimes cannot distinguish between them at the interface. This leads to something called "coincident surface artifacts". Here's an example: a transparent, light pink cone sitting on a blue cube:
#include "colors.inc"
#include "finish.inc"
camera {location <5,10,-8> look_at <0,0,0> angle 35}
light_source {<10,50,-10> color White}
light_source {<20,-40,20> color White}
background {color White}
#declare Thing = union {
box {<-1,-1,-1>, <1,1,1> pigment {color Blue}}
cone {<0,1,0>, 1, <0,5,0>, 0
texture {pigment {color rgbf <1,0.9,0.9,1>}
finish {ambient 0 diffuse 0 reflection 0.2
specular 0.2 roughness 0.001
refraction 1 ior 1.05}
}
}
}
object {Thing}
Rendered, this becomes:
You can see that there are ugly speckles at the places where the cone meets the box: since both objects have a surface in exactly the same place, POV-Ray sometimes can't tell them apart, and so some points get the texture of the cube, others that of the cone. To solve this, simply make one of the objects slightly larger or smaller so that there's a little overlap. Here, make the box very slightly taller: box {<-1,-1,-1>, <1,1.001,1> pigment {color Blue}}
leaving the rest of the file alone. Now, we get:
The change of 0.001 units has no visible effect on the size of the box, but the ugly coincident surface artifacts are gone. In general, it's always a good idea to have objects overlap slightly. Simple Programming: #if ... #end and #while ... #endPOV-Ray supports some limited programming functions. Of these, the most important are the Using #ifUse
#include "colors.inc"
#include "textures.inc"
#include "finish.inc"
camera {location <0,0,-80> look_at <0,0,0> angle 30}
light_source {<0,0,-50> color White}
#declare Flag = -1
#if (Flag > 0)
box {<-10,-10,0>, <10,10,0.1> pigment {White_Marble}}
#else
box {<-10,-10,0>, <10,10,0.1> pigment {Jade}}
#end
Render this, and we get:
If the statement after the In our example, the expression
Use Using #whileUse object {Block rotate y*45}
We can use a
#declare Block =
box {<0,0,0>, <0.5,2,1>
pigment {color Gray80}
translate <5,0,0>}
#declare Count = 0
#declare Steps = 12
#declare Angle = 360/Steps
#while (Count < Steps)
object {Block rotate y*Count*Angle}
#declare Count = Count + 1
#end
What does this code do? First, it defines the gray standing block. Then, it defines three variables using What does the loop itself do? First, it creates a Second, the loop increments Count. This has to be done explicitly with a Anyway, let's see what this scene looks like:
Let's make one small change to the code: change Steps to 16, and re-render:
Wow. All that changed was one silly little digit. Use |