RoundEdge 1.3 User Manual

A library module from the Persistence of Vision Ray Tracer (POV-Ray) Object Collection.

Abstract

[Demo image] Perfectly sharp edges are rare in real life. Blunting or rounding-off 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 ray-traced scene,” and “Wow!”

Unfortunately, with CSG this task is tedious and time-consuming. 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.


Table of Contents


Overview

Downloaded Files

Each italicized n in the filenames represents a decimal digit.

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 (30 images)
roundedge.pov A demonstration scene file, which was used to render the sample illustrations in this manual
READMEnnnnnn.html Important information about using the 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
cc-LGPL-a.png Administrative files
Versionnnnnnn.js

Note: Please compare the contents of the zip archive with the above table to make sure that all 30 illustration files are present; in some previous versions of RoundEdge, some of these files failed to upload. (Do this even if you have a previous version of RoundEdge, as the numbering of the illustrations has changed.) If any illustrations are missing from this archive, they can be generated (after you have unzipped the package) by running POV-Ray with these command line arguments:

+Iroundedge.pov +W240 +H180 Declare=Rad=1 +A0.05 +AM2 +R3 +KFF30 +Oroundedge_

If you are using POV-Ray 3.7, add +FJ Compression=90 to the command line. If you are using POV-Ray 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.

Table of contents


Usage

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.

Invalid Arguments

The descriptions of the objects assume valid arguments. If the arguments are not valid (for example, a negative radius), then the shape is undefined, 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.

Prerequisites

Requires POV-Ray version 3.5 or later.

Namespace Compliance

All file names in this module and all global and local identifiers defined in roundedge.inc comply 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, shapes.inc, and transforms.inc are used by roundedge.inc.

Table of contents


Joint Macros

RE_Corner_join (rBlob)

[Demo of RE_Corner_join()] An instant blob for the point of intersection of three orthogonal planes. It can be used to patch the Y-shaped seams left by the straight join macros. The joint is at the origin, and the curve faces the positive x-y-z 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.

Argument

rBlob:
The radius of the blob curve.

Table of contents

RE_Round_join (RPost, rBlob)

[Demo of RE_Round_join()] 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.

Arguments

RPost:
The radius of the post.
rBlob:
The radius of the blob curve.

Table of contents

RE_Round_inside_join (RHollow, rBlob)

[Demo of RE_Round_inside_join()] 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.

Arguments

RHollow:
The radius of the hollow space.
rBlob:
The radius of the blob curve.

Table of contents

RE_Straight_join_x (v_Start, End_x, rBlob, Dir)

[Demo of RE_Straight_join_x(), RE_Straight_join_y(), and RE_Straight_join_z()] An instant blob for the join between a y-normal plane and a z-normal plane. To avoid potential coincident surfaces, the object overlaps the line of intersection.

Arguments

These arguments may seem odd, but they were chosen to minimize typing and mental effort.

v_Start:
One end point of the intersection.
End_x:
The scalar x value of the other end point.
rBlob:
The radius of the blob curve.
Dir:
Rotation about the line of intersection, in degrees.

RE_Straight_join_y (v_Start, End_y, rBlob, Dir)

An instant blob for the join between an x-normal plane and a z-normal plane. To avoid potential coincident surfaces, the object overlaps the line of intersection.

Arguments

These arguments may seem odd, but they were chosen to minimize typing and mental effort.

v_Start:
One end point of the intersection.
End_y:
The scalar y value of the other end point.
rBlob:
The radius of the blob curve.
Dir:
Rotation about the line of intersection, in degrees.

RE_Straight_join_z (v_Start, End_z, rBlob, Dir)

An instant blob for the join between an x-normal plane and a y-normal plane. To avoid potential coincident surfaces, the object overlaps the line of intersection.

Arguments

These arguments may seem odd, but they were chosen to minimize typing and mental effort.

v_Start:
One end point of the intersection.
End_z:
The scalar z value of the other end point.
rBlob:
The radius of the blob curve.
Dir:
Rotation about the line of intersection, in degrees.

Table of contents


Edge Macros

RE_Elliptorus_mesh (RxMajor, RzMajor, rMinor, ThetaRes, PhiRes)

[Demo of RE_Elliptorus_mesh()] 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 x-axis for better viewing.) The mesh can be used in CSG differences and intersections.

Arguments

RxMajor:
The major radius in the x-direction.
RzMajor:
The major radius in the z-direction.
rMinor:
The nominal minor radius.
ThetaRes:
The number of longitudinal mesh divisions, which must be at least 4.
PhiRes:
The number of latitudinal mesh divisions, which must be at least 4.

RE_Elliptorus_octant (RxMajor, RzMajor, rMinor, ThetaRes, PhiRes)

[Demo of RE_Elliptorus_mesh_octant()] 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 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.)

Arguments

RxMajor:
The major radius in the x-direction.
RzMajor:
The major radius in the z-direction.
rMinor:
The nominal minor radius.
ThetaRes:
The number of longitudinal mesh divisions, which must be at least 1.
PhiRes:
The number of latitudinal mesh divisions, which must be at least 2. Use an even number for best results.

Table of contents

RE_Parabolic_torus (H, R)

[Demo of RE_Parabolic_torus()] A circle of radius R parallel to the y-z plane, swept along the curve y = Hx2 | 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.

Arguments

H:
The amplitude of the parabola.
R:
The minor radius.

Table of contents


Rounded Cylinder Macros

RE_Cylinder (A, B, ROuter, rEdge, Use_merge)

[Demo of RE_Cylinder()] A wrapper for macro Round_Cylinder() with several enhancements:

Arguments

A, B:
The end points of the cylinder.
ROuter:
The radius of the cylinder.
rEdge:
The radius of the edges of the cylinder.
Use_merge:
Whether or not to use a CSG merge. In general, pass yes if the object is to be transparent, no otherwise.

Table of contents

RE_Cylinder_end (A, B, ROuter, rEdge, Use_merge)

[Demo of RE_Cylinder_end()] A cylinder that is rounded on one end. The resulting object will fit snugly within cylinder { A, B, ROuter }.

Arguments

A:
The rounded end point of the cylinder.
B:
The flat end point of the cylinder.
ROuter:
The radius of the cylinder.
rEdge:
The radius of the rounded edge.
Use_merge:
Whether or not to use a CSG merge. In general, pass yes if the object is to be transparent, no otherwise.

Table of contents

RE_Hole (A, B, ROuter, RInner, rEdge, Use_merge)

[Demo of RE_Hole()] 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 }.

Arguments

A, B:
The end points of the cylinder.
ROuter:
The radius of the cylinder.
RInner:
The inner radius of the hole.
rEdge:
The radius of the rounded edges.
Use_merge:
Whether or not to use a CSG merge. In general, pass yes if the object is to be transparent, no otherwise.

Table of contents

RE_Hole_end (A, B, ROuter, RInner, rEdge, Use_merge)

[Demo of RE_Hole_end()] 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 }.

Arguments

A:
The end point of the cylinder with the rounded opening.
B:
The end point of the cylinder with the sharp opening.
ROuter:
The radius of the cylinder.
RInner:
The inner radius of the hole.
rEdge:
The radius of the rounded edge.
Use_merge:
Whether or not to use a CSG merge. In general, pass yes if the object is to be transparent, no otherwise.

Table of contents

RE_Hole_minimal (A, B, RInner, rEdge, Use_merge)

[Demo of RE_Hole_minimal()] 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 }.

Arguments

A, B:
The end points of the cylinder.
RInner:
The inner radius of the hole.
rEdge:
The radius of the rounded edges.
Use_merge:
Whether or not to use a CSG merge. In general, pass yes if the object is to be transparent, no otherwise.

Table of contents

RE_Hole_end_minimal (A, B, RInner, rEdge, Use_merge)

[Demo of RE_Hole_end_minimal()] 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 }.

Arguments

A:
The end point of the cylinder with the rounded opening.
B:
The end point of the cylinder with the sharp opening.
RInner:
The inner radius of the hole.
rEdge:
The radius of the rounded edge.
Use_merge:
Whether or not to use a CSG merge. In general, pass yes if the object is to be transparent, no otherwise.

Table of contents

RE_Washer (A, B, ROuter, RInner, rEdge, Use_merge)

[Demo of RE_Washer()] 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 }.

Arguments

A, B:
The end points of the cylinder.
ROuter:
The outer radius of the cylinder.
RInner:
The inner radius of the hole.
rEdge:
The radius of the rounded edges.
Use_merge:
Whether or not to use a CSG merge. In general, pass yes if the object is to be transparent, no otherwise.

Table of contents

RE_Washer_end (A, B, ROuter, RInner, rEdge, Use_merge)

[Demo of RE_Washer_end()] 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 }.

Arguments

A:
The end point of the rounded side of the cylinder.
B:
The end point of the flat side of the cylinder.
ROuter:
The outer radius of the cylinder.
RInner:
The inner radius of the hole.
rEdge:
The radius of the rounded edges.
Use_merge:
Whether or not to use a CSG merge. In general, pass yes if the object is to be transparent, no otherwise.

Table of contents


Rounded Box Macros

Summary

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. 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 pre-rotated into various orientations by the macros.

All of the rounded box macros take the same set of arguments:

A, B:
Opposite points of the box.
rEdge:
The radius of the edges of the box.
Use_merge:
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 }.

RE_Box (A, B, rEdge, Use_merge)

[Demo of RE_Box()] A wrapper for macro Round_Box() with two enhancements:

Table of contents

RE_Box_x (A, B, rEdge, Use_merge)

[Demo of RE_Box_x(), RE_Box_y(), and RE_Box_z()] A box with the four edges in the x-direction rounded, like a can of sardines on its side.

RE_Box_y (A, B, rEdge, Use_merge)

A box with the four edges in the y-direction rounded, like a can of sardines.

RE_Box_z (A, B, rEdge, Use_merge)

A box with the four edges in the z-direction rounded, like a can of sardines on its side.

Table of contents

RE_Box_left (A, B, rEdge, Use_merge)

[Demo of RE_Box_left() and RE_Box_right()] A box with the four corners on the −x side and the eight adjacent edges rounded.

RE_Box_right (A, B, rEdge, Use_merge)

A box with the four corners on the +x side and the eight adjacent edges rounded.

RE_Box_up (A, B, rEdge, Use_merge)

[Demo of RE_Box_up() and RE_Box_down()] A box with the four corners on the +y side and the eight adjacent edges rounded.

RE_Box_down (A, B, rEdge, Use_merge)

A box with the four corners on the −y side and the eight adjacent edges rounded.

RE_Box_near (A, B, rEdge, Use_merge)

[Demo of RE_Box_near() and RE_Box_far()] A box with the four corners on the −z side and the eight adjacent edges rounded.

RE_Box_far (A, B, rEdge, Use_merge)

A box with the four corners on the +z side and the eight adjacent edges rounded.

Table of contents

RE_Box_x_up (A, B, rEdge, Use_merge)

[Demo of RE_Box_x_up(), RE_Box_x_down(), RE_Box_x_near(), and RE_Box_x_far()] A box with the two top edges in the x-direction rounded.

RE_Box_x_down (A, B, rEdge, Use_merge)

A box with the two bottom edges in the x-direction rounded.

RE_Box_x_near (A, B, rEdge, Use_merge)

A box with the two edges in the x-direction on the −z side rounded.

RE_Box_x_far (A, B, rEdge, Use_merge)

A box with the two edges in the x-direction on the +z side rounded.

Table of contents

RE_Box_y_left (A, B, rEdge, Use_merge)

[Demo of RE_Box_y_left(), RE_Box_y_right(), RE_Box_y_near(), and RE_Box_y_far()] A box with the two edges in the y-direction on the −x side rounded.

RE_Box_y_right (A, B, rEdge, Use_merge)

A box with the two edges in the y-direction on the +x side rounded.

RE_Box_y_near (A, B, rEdge, Use_merge)

A box with the two edges in the y-direction on the −z side rounded.

RE_Box_y_far (A, B, rEdge, Use_merge)

A box with the two edges in the y-direction on the +z side rounded.

Table of contents

RE_Box_z_up (A, B, rEdge, Use_merge)

[Demo of RE_Box_z_up(), RE_Box_z_down(), RE_Box_z_left(), and RE_Box_z_right()] A box with the two top edges in the z-direction rounded.

RE_Box_z_down (A, B, rEdge, Use_merge)

A box with the two bottom edges in the z-direction rounded.

RE_Box_z_left (A, B, rEdge, Use_merge)

A box with the two edges in the z-direction on the −x side rounded.

RE_Box_z_right (A, B, rEdge, Use_merge)

A box with the two edges in the z-direction on the +x side rounded.

Table of contents


Isosurface Functions

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_Pn_” in roundedge.inc, in order to avoid a POV-Ray namespace scope feature. In this document, these prefixes are omitted for clarity.

RE_fn_Blob (Value, Blob)

[Demo of RE_fn_Blob()] 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).

Arguments

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

Usage

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> } }
}

RE_fn_Blob2 (Value, Blob)

[Demo of RE_fn_Blob2()] 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.

Arguments

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

Usage

  1. Add RE_fn_Blob2() of all base functions.
  2. Take the square root of the sum. (This step is not strictly necessary; however, it stabilizes the gradient and is well worth the overhead.) RE_fn_Blob2() always returns a non-negative 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 is non-negative, the isosurface can fail silently, without halting the render.

  3. Subtract from 1.

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.

Editorial

Why use the blob primitive?
It is highly optimized by the competent POV-Ray team; it’s much faster than isosurface.
Individual components can have their own textures.
Why use isosurface blobbing?
Arbitrary component shapes can be used, not just spheres and cylinders.
Why use RE_fn_Blob() or RE_fn_Blob2() instead of the isosurface blobbing methods suggested in the POV-Ray documentation?
RE_fn_Blob() and RE_fn_Blob2() match the curves of POV-Ray 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().

Table of contents

RE_fn_Hole (x, y, z, RMajor, rMinor)

[Demo of RE_fn_Hole()] A slab with a rounded-edged hole punched through it, equivalent to RE_Hole (-rMinor*y, rMinor*y, , RMajor - rMinor, rMinor, 1). It is intended for use with isosurface blobs.

Arguments

RMajor:
The radius of the hole.
rMinor:
The minor radius of the rounded edge.

Table of contents


RE_fn_Parabolic_torus (x, y, z, H, R)

[Demo of RE_fn_Parabolic_torus()] A circle of radius R parallel to the y-z plane, swept along the curve y = Hx2 | z = 0. Slower, but better behaved than macro RE_Parabolic_torus(). Check the message window to determine max_gradient.

Arguments

H:
The amplitude of the parabola.
R:
The minor radius of the rounded edge.

Table of contents


RE_fn_Wheel (x, y, z, RMajor, rMinor)

[Demo of RE_fn_Wheel()] A merge of a torus and a cylinder, equivalent to RE_Cylinder (-rMinor*y, rMinor*y, RMajor + rMinor, rMinor, 1). It is intended for use with isosurface blobs.

Arguments

RMajor:
The major radius of the torus.
rMinor:
The minor radius of the rounded edge.

Table of contents


Blob Assist Functions

Note: All function arguments are prefixed with “RE_Pn_” in roundedge.inc, in order to avoid a POV-Ray 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 POV-Ray Reference, but I feel the new names are more intuitive and easier to recall. The old function names still work.

RE_fn_Blob_surface_radius (RField, Strength)

[Demo of RE_fn_Blob_surface_radius()] 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.

Arguments

RField:
The field radius of the component.
Strength:
The field strength of the component.

RE_fn_Blob_field_radius (RSurface, Strength)

[Demo of RE_fn_Blob_field_radius() and RE_fn_Blob_strength()] 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 half-torus.

Arguments

RSurface:
The desired surface radius of the component.
Strength:
The field strength of the component.

RE_fn_Blob_strength (RSurface, RField)

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 half-torus.

Arguments

RSurface:
The desired surface radius of the component.
RField:
The field radius of the component.

Table of contents


Other Identifiers

Parameters

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 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, they may be modified prior to using the macros.

Reference Constant

Identifier Type Description Value
ROUNDEDGE_VERSION float The RoundEdge version, in case the caller needs to know. 1.3

Internal Identifiers

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.

Table of contents


About RoundEdge

Copyright © 2008 – 2013 Richard Callwood III. Some rights reserved. Licensed under the Creative Commons-GNU Lesser General Public License.

Change Log

Version Date Notes
1.0 September 2, 2008
  • Module elements are compiled and adapted for the Object Collection.
1.1 June 8-9, 2012 (incomplete upload)
  • Corner join and round inside join are added.
1.2 March 1, 2013 (incomplete upload)
  • Module is made compatible to POV-Ray 3.5.
  • Version identifier is added.
  • Elliptical toroids are added.
1.3 June 15, 2013
  • Blob assist functions are renamed.
  • The demo scene and documentation are updated, most importantly concerning sqrt() calls.

Acknowledgements

Table of contents