Rounded L-Prism (rlp) v0.2
2010 Samuel T. Benge
Contents
1.0 New in this Version
1.1 Introduction
1.2 Basic Usage
1.3 The Macros
1.3.1 Object Macros
rlp(pts, z1, z2, d_rad, offs)
rlp_chamfered(pts, z1, z2, d_rad, bev)
1.3.2 Pointset and Subset Manipulation Macros
rlp_scale(pts, scl)
rlp_scale_all(pts, scl)
rlp_rotate(pts, rot)
rlp_rotate_all(pts, rot)
rlp_translate(pts, trans)
rlp_translate_all(pts, trans)
rlp_set_radii(pts, rad)
rlp_flatten_all(pts)
rlp_reverse(pts)
rlp_shift(pts, offs)
rlp_shift_all(pts, offs)
1.3.3 Shape Macros
rlp_square(sz)
rlp_rectangle(sz_xy)
rlp_n_gon(radius, n_pts, rounding)
rlp_star(radius, n_pts, inset, r1, r2)
1.4 Things You Can Declare
rlp_bevels
rlp_types
rlp_enforce_roundness
1.5 Limitations
1.6 Troubleshooting
1.7 Tips
1.8 Contact
1.0 New in this Version:
* sharp corners
* pointset and subset transforms
* custom beveling and bevel types for individual subsets
* four subset shape primitives
* improved autofitting
* true zero-beveling
* more accurate
* faster parsing speed
1.1 Introduction
The rlp macros will create beveled, rounded prism objects from a series of user-defined points.
For each point, a custom radius may be given, causing rounding at that corner. These objects
can simplify the scene creation process, and may be used for things like machine parts, architecture, fonts, logos and other such items.
They were designed to render faster than their traditional CSG equivalents.
1.2 Basic Usage
To make an rlp object, you must specify a series of points which make up a pointset. These
should be in the following structure:
array[num_subsets]{
subset_1,
subset_2,
subset_3,
...
}
where each subset is a one-dimensional array in this format:
array[num_points]{
point_1,
point_2,
point_3,
...
}
in which each point is a 3D vector like so:
< x, y, rad >
"x" and "y" are the x & y positions for that point, and rad is the corner radius. The radius
will cause an arc to be fitted to that corner, effectively rounding it out.
A complete pointset would look like this:
array[1]{ // pointset
array[4]{ // subset
<-1, -1, 0>, // points
<-1, 1, 0>,
<1, 1, 0>,
<1, -1, 0>
}
}
The above would make a square. Notice that even though there is only one subset, it must wrapped
in a pointset array.
Each subset can be either a container or a hole. To make a container, write the subset so that
the points progress in a clockwise fashion. To make a hole, write the subset so that the points
go counter-clockwise. A hole should reside within the confines of a container. Any number of
containers and holes may be used, in any order, but there should be at least one container.
You may then invoke one of the object macros with your pointset.
1.3 The Macros
1.3.1 Object Macros
rlp(pts, z1, z2, d_rad, offs)
rlp_chamfered(pts, z1, z2, d_rad, bev)
* pts = a pointset
* z1 = z-offset 1
* z2 = z-offset 2
* d_rad = default corner radius
* bev = amount of beveling
The object will be oriented along the z-axis. It will start at z1, ending at z2.
d_rad is the default corner radius. It will be passed along if the third entry of any 3D vector
equals zero. So, if you give d_rad a value of 1 and use the square pointset described above, you
will get a circle. Setting this to zero is the only way to allow corners to have a zero radius.
bev is the amount of beveling for the entire object. It will be adjusted so that it never
exceeds half the distance between z1 and z2. However, it will not adjust itself to the geometry
you provide in your pointsets, so to keep bad things from happening, keep it low enough to accomodate them.
The rlp_chamfered version uses flat beveling, whereas the basic version creates an object with
rounded beveling.
The new sharp corners feature will create a sharp corner at any point which has a radius near 0.
To eliminate sharp inside corners, give that point any radius above 0. For outside points you
must "work past" the beveling by raising the radius until the corner is no longer sharp. You can
turn off this feature for outside corners by setting rlp_enforce_roundness to "true."
1.3.2 Pointset and Subset Manipulation Macros
These macros allow you to transform subsets or entire pointsets.
rlp_scale(pts, scl)
* pts = a point subset
* scl = a 2D vector, x/y scaling
Scales the points of a given subset. Be aware that non-uniform scaling might not preserve the
radii in your point subset.
rlp_scale_all(pts, scl)
* pts = a pointset
* scl = a 2D vector, x/y scaling
Scales the points of an entire pointset. Be aware that non-uniform scaling might not preserve
the radii in your pointset.
rlp_rotate(pts, rot)
* pts = a point subset
* rot = amount of rotation
Rotates the points of a given subset.
rlp_rotate_all(pts, rot)
* pts = a pointset
* rot = amount of rotation
Rotates the points of an entire pointset.
rlp_translate(pts, trans)
* pts = a point subset
* trans = a 2D vector, x/y translation
Translates the points of a given subset.
rlp_translate_all(pts, trans)
* pts = a pointset
* trans = a 2D vector, x/y translation
Translates the points for an entire pointset.
rlp_set_radii(pts, rad)
* pts = a point subset
* rad = new radii
Applies a uniform radius to all points in a subset.
rlp_flatten_all(pts)
* pts = a pointset
Drops the radii for all points in a complete pointset to zero. You can then give the object a
default radius when you invoke an rlp object macro.
rlp_reverse(pts)
* pts = a point subset
Reverses the order of the points in a subset. It is useful for making holes from subsets that
were originally containers, or vice-versus.
rlp_shift(pts, offs)
* pts = a point subset
* offs = offset amount
This will "shrink" or "fatten" a point subset. Positive values fatten the points, negative
values shrink them. You can use this in combination with rlp_reverse to make, for example,
borders for wooden signs. The point radii will be modified somewhat.
rlp_shift_all(pts, offs)
* pts = a pointset
* offs = offset amount
This will "shrink" or "fatten" an entire pointset. Positive values fatten the points, negative
values shrink them. The point radii will be modified somewhat.
1.3.3 Shape Macros
Here are some macros to create basic shapes for your subsets.
rlp_square(sz)
* sz = size of square, single value
Makes a square.
rlp_rectangle(sz)
* sz = size of rectangle, a 2D vector
Makes a rectangle.
rlp_n_gon(rad, npts, rounding)
* rad = radius of polygon
* npts = number of points
* rounding = amount of rounding for each point
It will make a polygonal shape for a subset. You can use it to quickly make tight-fitting
circles, bolt heads and other similar items. The minimum number of points is three.
rlp_star(rad, inset, npts, r1, r2)
* rad = radius of star
* inset = amount to push the inside corners inward (0 to <1 or int(< 0))
* npts = number of points
* r1 = amount of rounding for outside points
* r2 = amount of rounding for inside points
Makes a star shape. The minimum number of points is three.
If inset equals 0, then you will get an rlp_n_gon.
If inset is an integer and is less than 0, then the macro will automatically space the inset
points to make perfect star shapes. For example, if inset equals -1, then it will skip one
point, -2 and it will skip 2 points and so forth. If you skip too many points for your particular star,
you will get incorrect results.
1.4 Things You Can Declare
rlp_bevels
You can declare a 1D array called "rlp_bevels" which allows you to specify custom beveling for
individual subsets. For instance, if your pointset has 3 subsets, you declare it like so:
#declare rlp_bevels = array[3];
To change the beveling for the second subset, you would then do this:
#declare rlp_bevels[1] = 0.1;
It will only change the beveling for #declared entries, so you don't have to write out the
entire array. The values you declare will be reset before you call another rlp object macro.
rlp_types
You can declare a 1D array called "rlp_types" which allows you to specify what style of beveling
to give individual subsets. Two types are available: rounded (0) and chamfered (1). As an example, if your
pointset has 4 subsets, you would declare it like this:
#declare rlp_types = array[4];
To change the 3rd subset's beveling type to a chamfered bevel, you would do this:
#declare rlp_types[3] = 1;
It will only change the beveling type for #declared entries, so you don't have to write out the
entire array. The values you declare will be reset before you call another rlp object macro.
rlp_enforce_roundness
Declare this variable as 'true' to keep outside corners with low radii from becoming sharp. Inside
corners will still be sharp, and can be rounded out with a default radius when invoking an
rlp macro.
Example:
#declare rlp_enforce_roundness = true;
1.5 Limitations
Three consecutive points must not lie along the same 2D line. At best, if you do this, the rlp
object will not be correct. At worst, POV-Ray will abort the render with an error regarding a
degenerate plane normal. It is always best to use the simplest series of points to make your
object.
The objects cannot be used with merge, intersection or difference CSG operations. To work
around it, you can punch holes into them via the hole-creation method described above in conjunction
with custom beveling via rlp_bevels. You may also clip an rlp object using clipped_by
statements, which is a good way to join transparent objects or to remove unwanted geometry.
The objects are not fully clipped for transparency. This means that in some cases you will not
get correct results when using transparency. I may add full support for this in the future, if
somebody wants it. For now it's best to just use opaque objects, or settings which do not
cause too much overlap (you'll know it when you see it).
Autofitting is now a permanent feature. This is a mixed bag. On one hand, the autofitting that
is performed allows for more flexibility and ease of use. On the other hand, a point's radius
will sometimes be "pushed out" by neighboring points which have higher radii. There's a good
reason for doing it this way, but I won't go into it right now. I recommend keeping your radii
at the approximate sizes you need to get the desired result.
Inside corners will behave differently from outside corners when given the same radii. Again,
there was a good reason for doing it this way, and it has to do with the new sharp corners
feature.
1.6 Troubleshooting
Sometimes when designing an object, you may end up with a complete mess instead of what you
wanted. There are three main things which can go wrong:
1) Your beveling is too high. Drop it to zero and see if that doesn't fix it. Excessive
beveling can cause: jumbled geometry; POV-Ray to abort with a series of warnings and an error;
sharp corners to overextend themselves; an rlp object to sometimes flip itself upside-down;
degenerate cylinders.
2) You have written the subset(s) with the wrong rotation. Remember, clockwise for containers,
anti-clockwise for holes. You may use rlp_reverse to quickly change a subset to the correct
rotation.
3) You have points overlapping lines from other points. The base shape is a linear spline, and
the polygon used to cap the final object uses that same linear spline to make its base
shape. Polygons with overlapping geometry don't render correctly. An exception to this is
made for inside corners, where you may in fact get away with a little bit of overlap.
If you still have a screwed-up object, send me the file you are working on; there may be a bug
in my code.
Also, you may sometimes get "subscript out of range" and similar array errors. These are always
caused by the wrong type of array being given to the rlp macros. Check your code!
1.7 Tips
Sketch out your idea on paper. This way you can easily see how many points you need for a particular
subset, and it will help you to keep track of your points. You may discover that it
takes fewer points than you think!
To visualize your pointset at its basest form, and to see how it makes up a linear spline prism,
try this: flatten all your points, set the default radius to zero, and remove any beveling.
This way you can tell if your points overlap lines created from other points.
To seamlessly fit an rlp object to your scene's geometry, use rlp_bevels to give the container
for the rlp object zero beveling. For instance, if you have a square with an arch-shaped hole
and you want to fit it into a wall, give the containing square zero beveling.
If you intend to make a new container from a pre-existing hole, create a new rlp object to
avoid errors.
1.8 Contact
Since I don't want to be spammed, you'll have to unscramble the following letters to e-mail me:
esgetnb
4167253
and append: @hotmail.com
Happy Raytracing!