A library module from the Persistence of Vision Ray Tracer (POVRay) Object Collection.
Perfectly sharp edges are rare in real life. Blunting or roundingoff the edges of ray traced objects brings out specular highlights and other, more subtle lighting effects that can make the difference between “That’s a nice raytraced scene,” and “Wow!”
Unfortunately, with CSG this task is tedious and timeconsuming. The standard include file shapes.inc
has some helpful macros to assist with this task, but they are rather limited. RoundEdge builds upon shapes.inc
and adds some additional objects and functions.
The italicized nnnnnn in some of the file names represents the 6digit number that is in the name of the .zip
file.
Key Files  

File  Description 
roundedge.html 
The user manual (this document) 
roundedge.inc 
The RoundEdge software 
roundedge.jpg 
Sample output 
roundedge_ nn.jpg 
Illustrations of the various features, where the italicized nn represents a 2digit number (30 images) 
roundedge.pov 
A demonstration scene file, which was used to render the sample illustrations in this manual 
README nnnnnn.html 
Important information about using the POVRay Object Collection 
Other Files  
File  Description 
roundedge.css 
A file used by the user manual 
roundedge_description.txt 
A brief description of RoundEdge 
roundedge_keywords.txt 
A list of keywords 
roundedge_prereqs.txt 
Prerequisites (empty file) 
roundedge_thumbnail.jpg 
Sample output 
ccLGPLa.png 
Administrative files 
Version nnnnnn.js 
Note: Please compare the contents of the zip archive with the above table to make sure that all 30 illustration files are in the archive; in some previous versions of RoundEdge, some of these files failed to upload. The problem has already been addressed, but this upload is the first to test the fix.
If any illustrations are missing from the archive, they can be generated (after you have unzipped the package) by running POVRay with the following command line arguments. (Be sure not to omit the underscore at the end.)
+Iroundedge.pov +W240 +H180 Declare=Rad=1 +A0.05 +AM2 +R3 +KFF30 +Oroundedge_
If you are using POVRay 3.7, add +FJ Compression=90
to the command line. If you are using POVRay 3.5 or 3.6, you will need to convert the illustrations to JPEG format using a separate tool. To match the quality of the other illustrations, use quality 90 and chroma subsampling 1x1,1x1,1x1 or 4:4:4.
Do this even if you are installing over a previous version of RoundEdge, as, depending on your previous version, the numbering of the illustrations may have changed, and additional illustrations added.
Note: The file roundedge_cclgpl.png
is no longer used.
RoundEdge requires POVRay version 3.5 or later.
All file names in this module and all global and local identifiers defined in roundedge.inc
comply fully with the Object Collection naming standards, as revised August 2008 and proposed August 2012. The prefixes for this module are “roundedge
” and “RE
,” including any uppercase and lowercase variants; to avoid conflicts, do not declare identifiers that start with these prefixes plus an underscore.
The standard include files functions.inc
, math.inc
, shapes.inc
, and transforms.inc
are used by roundedge.inc
.
Include this file once prior to using any of the features of RoundEdge:
#include "roundedge.inc"
Including the file more than once is harmless, though unnecessary.
The descriptions of the objects assume valid arguments. If the arguments are not valid (for example, a negative radius), then the shape is undefined; that is, with no guarantee of what it will look like or that it will fit anywhere. To assist the user, a warning or error message will be issued.
An instant blob for the point of intersection of three orthogonal planes. It can be used to patch the Yshaped seams left by the straight join macros. The joint is at the origin, and the curve faces the positive xyz octant. (In the illustration, the RE_Corner_join()
object has been rotated to match the corner.) To avoid potential coincident surfaces, the object overlaps the origin.
Formal Parameter  Type  Description 

rBlob 
float  The radius of the blob curve. 
An instant blob for a vertical cylindrical post joined to a horizontal plane. The intersection of the post’s axis with the plane is at the origin. To avoid potential coincident surfaces, the bottom surface of the join is slightly below the origin.
Formal Parameter  Type  Description 

RPost 
float  The radius of the post. 
rBlob 
float  The radius of the blob curve. 
An instant blob for a vertical hollow cylinder joined to a horizontal plane. The intersection of the cylinder’s axis with the plane is at the origin. To avoid potential coincident surfaces, the join slightly overlaps the hollow cylinder, and bottom surface of the join is slightly below the origin.
Formal Parameter  Type  Description 

RHollow 
float  The radius of the hollow space. 
rBlob 
float  The radius of the blob curve. 
An instant blob for the join between a ynormal plane and a znormal plane. To avoid potential coincident surfaces, the object overlaps the line of intersection.
These arguments may seem odd, but they were chosen to minimize typing and mental effort.
Formal Parameter  Type  Description 

v_Start 
vector  One end point of the intersection. 
End_x 
float  The scalar x value of the other end point. 
rBlob 
float  The radius of the blob curve. 
Dir 
float  Rotation about the line of intersection, in degrees. 
An instant blob for the join between an xnormal plane and a znormal plane. To avoid potential coincident surfaces, the object overlaps the line of intersection.
These arguments may seem odd, but they were chosen to minimize typing and mental effort.
Formal Parameter  Type  Description 

v_Start 
vector  One end point of the intersection. 
End_y 
float  The scalar y value of the other end point. 
rBlob 
float  The radius of the blob curve. 
Dir 
float  Rotation about the line of intersection, in degrees. 
An instant blob for the join between an xnormal plane and a ynormal plane. To avoid potential coincident surfaces, the object overlaps the line of intersection.
These arguments may seem odd, but they were chosen to minimize typing and mental effort.
Formal Parameter  Type  Description 

v_Start 
vector  One end point of the intersection. 
End_z 
float  The scalar z value of the other end point. 
rBlob 
float  The radius of the blob curve. 
Dir 
float  Rotation about the line of intersection, in degrees. 
A toroid mesh that can serve as a rounded edge for scaled cylinders, when it is desired that the edge radius not be scaled with the cylinders. The central curve, the extreme inner curve, and the extreme outer curve are all ellipses (within the resolution of the mesh). Note that a sphere sweep does not satisfy this condition (except for the boundary cases where the ellipses are circles), as the required shape does not have a constant minor radius.
The toroid is oriented horizontally. (In the illustration, it has been rotated 90° about the xaxis for better viewing.) The mesh is closed, and can therefore be used in CSG differences and intersections.
Formal Parameter  Type  Description 

RxMajor 
float  The major radius in the xdirection. 
RzMajor 
float  The major radius in the zdirection. 
rMinor 
float  The nominal minor radius. 
ThetaRes 
float  The number of longitudinal mesh divisions, which must be at least 4. 
PhiRes 
float  The number of latitudinal mesh divisions, which must be at least 4. 
The +x, +y, +z octant of a horizontally oriented elliptical toroid, implemented as a mesh. The object is intended to serve as a rounded edge for scaled cylinders, when it is desired that the edge radius not be scaled with the cylinders. The central curve, the extreme inner curve, and the extreme outer curve are all elliptical arcs (within the resolution of the mesh). Note that a sphere sweep does not satisfy this condition (except for the boundary cases where the arcs are circular), as the required shape does not have a constant minor radius.
The mesh is closed, and can therefore be used in CSG differences and intersections. The “flat” surfaces are bowed outward slightly to avoid potential coincident surfaces. (There are still intermittent artifacts resembling coincident surfaces, but I haven’t yet identified the cause.)
Formal Parameter  Type  Description 

RxMajor 
float  The major radius in the xdirection. 
RzMajor 
float  The major radius in the zdirection. 
rMinor 
float  The nominal minor radius. 
ThetaRes 
float  The number of longitudinal mesh divisions, which must be at least 1. 
PhiRes 
float  The number of latitudinal mesh divisions, which must be at least 2. Use an even number for best results. 
A circle of radius R
parallel to the yz plane, swept along the curve y = H
x^{2}  z = 0.
The user is responsible for clipping and bounding. The objects are prone to floating point error, so an isosurface function, RE_fn_Parabolic_torus()
, is also provided.
Formal Parameter  Type  Description 

H 
float  The amplitude of the parabola. 
R 
float  The minor radius. 
A replacement for macro Round_Cylinder()
with several enhancements:
RE_Cylinder()
, this generally results in faster renders. (This feature can be disabled by setting RE_Split_union
to on
.)
Round_Cylinder_Merge()
has artifacts for large, but valid, values of EdgeRadius
. For example:
#include "shapes.inc" object { Round_Cylinder_Merge (y, y, 1, 0.7) pigment { red 1 transmit 0.5 } }
These artifacts are eliminated in RE_Cylinder()
and in RE_Cylinder_end()
, below.
Formal Parameter  Type  Description 

A , B 
vector  The end points of the cylinder. 
ROuter 
float  The radius of the cylinder. 
rEdge 
float  The radius of the edges of the cylinder. 
Use_merge 
float/Boolean  Whether or not to use a CSG merge. In general, pass yes if the object is to be transparent, no otherwise. 
A cylinder that is rounded on one end. The resulting object will fit snugly within cylinder { A, B, ROuter }
.
Formal Parameter  Type  Description 

A 
vector  The rounded end point of the cylinder. 
B 
vector  The flat end point of the cylinder. 
ROuter 
float  The radius of the cylinder. 
rEdge 
float  The radius of the rounded edge. 
Use_merge 
float/Boolean  Whether or not to use a CSG merge. In general, pass yes if the object is to be transparent, no otherwise. 
A cylinder with a hole along the central axis.
The edges of the hole are rounded.
The resulting object will fit snugly within
cylinder { A, B, ROuter }
and snugly around
cylinder { A, B, RInner }
.
Formal Parameter  Type  Description 

A , B 
vector  The end points of the cylinder. 
ROuter 
float  The radius of the cylinder. 
RInner 
float  The inner radius of the hole. 
rEdge 
float  The radius of the rounded edges. 
Use_merge 
float/Boolean  Whether or not to use a CSG merge. In general, pass yes if the object is to be transparent, no otherwise. 
A cylinder with a hole along the central axis.
The edge of the hole at one end is rounded.
The resulting object will fit snugly within
cylinder { A, B, ROuter }
and snugly around
cylinder { A, B, RInner }
.
Formal Parameter  Type  Description 

A 
vector  The end point of the cylinder with the rounded opening. 
B 
vector  The end point of the cylinder with the sharp opening. 
ROuter 
float  The radius of the cylinder. 
RInner 
float  The inner radius of the hole. 
rEdge 
float  The radius of the rounded edge. 
Use_merge 
float/Boolean  Whether or not to use a CSG merge. In general, pass yes if the object is to be transparent, no otherwise. 
A cylinder with a hole along the central axis.
The edges of the hole are rounded, and the cylinder is just wide enough to cover the joint between perpendicular rounded boxes of the same edge radius.
The object will fit snugly around
cylinder { A, B, RInner }
.
Formal Parameter  Type  Description 

A , B 
vector  The end points of the cylinder. 
RInner 
float  The inner radius of the hole. 
rEdge 
float  The radius of the rounded edges. 
Use_merge 
float/Boolean  Whether or not to use a CSG merge. In general, pass yes if the object is to be transparent, no otherwise. 
A cylinder with a hole along the central axis.
One edge of the hole is rounded, and the cylinder is just wide enough to cover the joint between perpendicular rounded boxes of the same edge radius.
The object will fit snugly around
cylinder { A, B, RInner }
.
Formal Parameter  Type  Description 

A 
vector  The end point of the cylinder with the rounded opening. 
B 
vector  The end point of the cylinder with the sharp opening. 
RInner 
float  The inner radius of the hole. 
rEdge 
float  The radius of the rounded edge. 
Use_merge 
float/Boolean  Whether or not to use a CSG merge. In general, pass yes if the object is to be transparent, no otherwise. 
A cylinder with a hole along the central axis.
The edges of the cylinder and the hole are rounded.
The resulting object will fit snugly within
cylinder { A, B, ROuter }
and snugly around
cylinder { A, B, RInner }
.
Formal Parameter  Type  Description 

A , B 
vector  The end points of the cylinder. 
ROuter 
float  The outer radius of the cylinder. 
RInner 
float  The inner radius of the hole. 
rEdge 
float  The radius of the rounded edges. 
Use_merge 
float/Boolean  Whether or not to use a CSG merge. In general, pass yes if the object is to be transparent, no otherwise. 
A cylinder with a hole along the central axis.
The edges on one side of the cylinder and the hole are rounded.
The resulting object will fit snugly within
cylinder { A, B, ROuter }
and snugly around
cylinder { A, B, RInner }
.
Formal Parameter  Type  Description 

A 
vector  The end point of the rounded side of the cylinder. 
B 
vector  The end point of the flat side of the cylinder. 
ROuter 
float  The outer radius of the cylinder. 
RInner 
float  The inner radius of the hole. 
rEdge 
float  The radius of the rounded edges. 
Use_merge 
float/Boolean  Whether or not to use a CSG merge. In general, pass yes if the object is to be transparent, no otherwise. 
The first macro creates a box with all its edges rounded off. The remaining macros create boxes with only some rounded edges. The intent of the partially rounded box macros is to reduce object counts in situations where rounding all edges is unnecessary. This can result in significantly faster renders where differences, intersections, or photons are used.
Despite the large number of macros in this section, there are only four basic shapes: the fully rounded box; and three partially rounded boxes that are prerotated into various orientations by the macros.
All of these rounded box macros take the same set of arguments:
Formal Parameter  Type  Description 

A , B 
vector  Opposite points of the box. 
rEdge 
float  The radius of the edges of the box. 
Use_merge 
float/Boolean  Whether or not to use a CSG merge. In general, pass yes if the object is to be transparent, no otherwise. 
The resulting object will fit snugly within box { A, B }
.
A wrapper for macro Round_Box()
with two enhancements:
Round_Box_Union()
, this generally results in faster renders. (This feature can be disabled by setting RE_Split_union
to on
.)
A box with the four edges in the xdirection rounded, like a can of sardines on its side.
A box with the four edges in the ydirection rounded, like a can of sardines.
A box with the four edges in the zdirection rounded, like a can of sardines on its side.
A box with the four corners on the −x side and the eight adjacent edges rounded.
A box with the four corners on the +x side and the eight adjacent edges rounded.
A box with the four corners on the +y side and the eight adjacent edges rounded.
A box with the four corners on the −y side and the eight adjacent edges rounded.
A box with the four corners on the −z side and the eight adjacent edges rounded.
A box with the four corners on the +z side and the eight adjacent edges rounded.
A box with the two top edges in the xdirection rounded.
A box with the two bottom edges in the xdirection rounded.
A box with the two edges in the xdirection on the −z side rounded.
A box with the two edges in the xdirection on the +z side rounded.
A box with the two edges in the ydirection on the −x side rounded.
A box with the two edges in the ydirection on the +x side rounded.
A box with the two edges in the ydirection on the −z side rounded.
A box with the two edges in the ydirection on the +z side rounded.
A box with the two top edges in the zdirection rounded.
A box with the two bottom edges in the zdirection rounded.
A box with the two edges in the zdirection on the −x side rounded.
A box with the two edges in the zdirection on the +x side rounded.
For all of these functions, the default threshold of 0.0 is assumed.
Note: All function arguments (other than x
, y
, and z
) are prefixed with “RE_P
n_
” in roundedge.inc
, in order to avoid a POVRay namespace scope feature. In this document, these prefixes are omitted for clarity.
An isosurface blobbing function. This function is based on the formula for the blob primitive, so when it’s used with f_sphere()
, it gives results identical to the blob primitive (within the limits of the accuracy of the isosurface).
Formal Parameter  Type  Description 

Value 
float  The unblobbed function value f (x, y, z, …) 
Blob 
float  “Blobbiness.” Depending on the function, this is typically:

Subtract RE_fn_Blob()
of all base functions from 1. For example:
isosurface { function { 1  RE_fn_Blob (abs(x) + abs(z)  1, 0.3)  RE_fn_Blob (f_sphere (0, y, z, 0.8), 0.2) } max_gradient 4 / 0.2 contained_by { box { <2.5, 2, 1>, <2.5, 2, 1> } } }
Another isosurface blobbing function. This function uses an alternate formula that gives smoother curves for some joins than the standard blob formula. Perpendicular planes yield a cylindrical blob with this formula, making it useful in conjunction with the cylinder, sphere, and torus primitives.
Formal Parameter  Type  Description 

Value 
float  The unblobbed function value f (x, y, z, …) 
Blob 
float  “Blobbiness.” Depending on the function, this is typically:

RE_fn_Blob2()
of all base functions.
RE_fn_Blob2()
always returns a nonnegative number, so it is not necessary to check for a negative square root operand unless you are using a negative blob component.
Warning: It has come to my attention that a negative square root operand, in the context of an isosurface, does not raise an exception. If you use a negative blob component without checking that the sum of the components is nonnegative, the isosurface can fail silently, without halting the render.
Example:
isosurface { function { 1  sqrt ( RE_fn_Blob2 (abs(x) + abs(z)  1, 0.3) + RE_fn_Blob2 (f_sphere (0, y, z, 0.8), 0.2) ) } max_gradient 1.3 / 0.2 contained_by { box { <2.5, 2, 1>, <2.5, 2, 1> } } }
Note: the max gradient will typically be inversely proportional to the smallest Blob
argument.
blob
primitive?
isosurface
.
RE_fn_Blob()
or RE_fn_Blob2()
instead of the isosurface blobbing methods suggested in the POVRay documentation?
RE_fn_Blob()
and RE_fn_Blob2()
match the curves of POVRay primitives, allowing primitive and isosurface blob to work together. The primitives can then model the bulk of the object, resulting in dramatically shorter rendering times.
The illustrations for RE_fn_Hole()
and RE_fn_Wheel()
demonstrate seamless joins between RE_fn_Blob2()
blobs and RE_Straight_join_x()
.
A slab with a roundededged hole punched through it, equivalent to
RE_Hole (rMinor*y, rMinor*y,
∞, RMajor  rMinor, rMinor, 1)
.
Its utility is with isosurface blobs. In the illustration, the colored patch is an isosurface of RE_fn_Hole()
blobbed using RE_fn_Blob2()
.
Formal Parameter  Type  Description 

RMajor 
float  The radius of the hole. 
rMinor 
float  The minor radius of the rounded edge. 
A circle of radius R
parallel to the yz plane, swept along the curve y = H
x^{2}  z = 0. Slower, but better behaved than macro RE_Parabolic_torus()
. Check the message window to determine max_gradient
.
Formal Parameter  Type  Description 

H 
float  The amplitude of the parabola. 
R 
float  The minor radius of the rounded edge. 
A merge of a torus and a cylinder, equivalent to
RE_Cylinder (rMinor*y, rMinor*y, RMajor + rMinor, rMinor, 1)
.
Its utility is with isosurface blobs. In the illustration, the colored patch is an isosurface of RE_fn_Wheel()
blobbed using RE_fn_Blob2()
.
Formal Parameter  Type  Description 

RMajor 
float  The major radius of the torus. 
rMinor 
float  The minor radius of the rounded edge. 
Note: All function arguments are prefixed with “RE_P
n_
” in roundedge.inc
, in order to avoid a POVRay namespace scope feature. In this document, these prefixes are omitted for clarity.
Note: Functions RE_fn_Blob_surface_radius()
and RE_fn_Blob_field_radius()
were originally called RE_fn_Blob_distance()
and RE_fn_Blob_radius()
, respectively. The old names reflect the terminology in the POVRay Reference, but I feel the new names are more intuitive and easier to recall. The old function names still work.
Returns the surface radius of a blob component, given the field radius and field strength. The default blob threshold of 1.0 is assumed. Use this function when the exact size of a blob component needs to be known. In the illustration, the size of the opening is matched to the blob.
Formal Parameter  Type  Description 

RField 
float  The field radius of the component. 
Strength 
float  The field strength of the component. 
Returns the field radius that yields a blob component of the desired surface radius. The default blob threshold of 1.0 is assumed. Use this function when the exact size of a blob component is important. In the illustration, the blob is matched seamlessly to the halftorus.
Formal Parameter  Type  Description 

RSurface 
float  The desired surface radius of the component. 
Strength 
float  The field strength of the component. 
Returns the field strength that yields a blob component of the desired surface radius. The default blob threshold of 1.0 is assumed. Use this function when the exact size of a blob component is important. In the illustration above, the blob is matched seamlessly to the halftorus.
Formal Parameter  Type  Description 

RSurface 
float  The desired surface radius of the component. 
RField 
float  The field radius of the component. 
Identifier  Type  Description  Default 

RE_MORE 
float  Slightly greater than one, for avoiding coincident surfaces.  1.001 
RE_LESS 
float  Slightly less than one, for avoiding coincident surfaces.  0.999 
RE_ABIT 
float  Slightly greater than zero, for avoiding coincident surfaces.  0.001 
RE_Split_union 
float/Boolean  If off , then split_union off will be applied to the various rounded box and rounded cylinder unions. This can result in faster rendering when photons are used. 
off 
If the user finds the default values unsatisfactory, these parameters may be modified at any time prior to using a macro.
Identifier  Type  Description  Value 

ROUNDEDGE_VERSION 
float  The RoundEdge version, in case the scene file needs that information.  1.31 
Any identifiers in roundedge.inc
that are not documented in this manual are considered “private” or “protected,” and are subject to change or elimination in a future update.
Version  Date  Notes 

1.0  2008 September 2 – 4 

1.1  2012 June 8 – 9 (incomplete upload) 

1.2  2013 March 1 (incomplete upload) 

1.3  2013 June 15 

1.3.1  2016 January 23 
