rounded_lprism.inc readme

2010 Samuel Benge

____________
Introduction

The rounded_lprism macros will construct rounded objects from sets of user-
defined points. The basic shape is a beveled, linear_spline prism, but you
can also define the amount of global or per-point rounding for the spline
corners. For instance, a simple cube shape is described by four points.
With the right amount of corner rounding, the cube will become a cylinder,
plus it will be beveled. You can control the depth of the object when you
invoke the macro.

Holes can be punched through the object by specifying sets of hole points.
These will also be rounded and beveled. Any number of holes may be used.

Like the Round_Box, Round_Cylinder, etc. macros in shapes.inc,
rounded_lprism will fit within its respective shape.

The object is composed of clipped polygons, boxes, cylinders and tori, so
it doesn't take forever to render. It's actually very fast.

I have included some example scenes. I recommend looking at them in this
order:

rounded_lprism_single.pov
rounded_lprism_holes.pov
rounded_lprism_holefill.pov
rounded_lprism_free.pov

_____________
The Structure

To produce linear_splines for rounded_lprism, you must provide sets of
points. A minimum of three points per set is required, since a triangle is
the smallest polygon.

The points you pass to the macro are in this form:

 #declare some_pts =
 array[n_sets]{
  array[n_points]{ outside point set },
  array[n_points]{ hole point set },
  array[n_points]{ hole point set },
  array[n_points]{ hole point set },
  array[n_points]{ hole point set },
  ...
 }

The master array holds all the point sets. Each sub-array is a single point
set, which in turn is a series of 3D vectors in this form:

 < xpos, ypos, radius >,
 < xpos, ypos, radius >,
 < xpos, ypos, radius >,
 ...

The first two entries in each 3D vector are the x/y position for that
point. The third entry is the amount of rounding for that point. If it is
zero, then the default radius will be used. But if it is more than zero, it
will then override the default radius you pass to the macro (more on that
below). You must specify a radius, as there needs to be a third entry.

The first point set always describes the containing linear_spline. To work
correctly, the outside points will need to be placed *clockwise*. Every
point set thereafter will be used for the holes. The points for them will
need to be placed *counter-clockwise*, or else you will experience problems.

Each point set must not be closed as you would normally close a prism's
linear_spline. Since these macros already know what a complete set is,
making the last point the same as the first would not only be redundant,
it could be disasterous. That is why, to make a square, you would only use
four points. It's easier that way.

If you want an object without holes, you would write its single point set
like so:

 #declare some_pts =
 array[1]{
  array[n_points]{ outside points }
 }

__________
The Macros

Contents:

 rounded_lprism_autofit
 rounded_lprism_free
 rounded_lprism_autofit_chamfered
 rounded_lprism_free_chamfered
 
 rounded_lprism_cage
 rounded_lprism_prism


rounded_lprism_autofit( pts, z1, z2, eRad_default, bevel )
rounded_lprism_free( pts, z1, z2, eRad_default, bevel )
rounded_lprism_autofit_chamfered( pts, z1, z2, eRad_default, bevel )
rounded_lprism_free_chamfered( pts, z1, z2, eRad_default, bevel )
 
 * pts          = an array holding the point sets
 * z1           = depth 1
 * z2           = depth 2
 * eRad_default = the default rounding for all points
 * bevel        = the amount of beveling for surface edges

z1 and z2 control the object's depth. The object will be extruded along
the z-axis beginning at z = z1 and extending to z = z2.

eRad_default will set a minimum rounding radius for all corners of the
spline. If this is zero, then you will get a beveled, basic linear_spline
prism. You can add specific radii for each point manually in the point
sets.

The last argument, "bevel", sets the beveling for the entire object. If it
is set to zero, then it will automatically be adjusted to a small, +0
value to keep bad artifacts from occuring. Therefore the object is *always*
beveled, but only by a tiny amount. There is no upper limit to the amount
of beveling, so you will have to use it carefully.


The Autofit and Free Versions in Detail

The autofit versions will make an object in which all the corner radii are
adjusted to fit properly. They keep arcs from overlapping other arcs. The
routine they perform is a kind of centerpoint evaluation. Basically, it
tests the distance between one point and the point next to it and finds the
center. It then tests the point on the other side, finds the distance,
then the center, and then chooses the lesser distance of the two and uses
it to govern the rounding radius for a corner. What all this means is that
you can plug a large value into eRad_default and gets lots of rounding
with out worrying whether or not the arcs are overlapping. The downside is
that you have less control over the final result, since the centerpoint
routine will often lower a radius below what you might want for a corner.

The free versions will make an object in which there is no upper limit to
the amount of rounding that can occur for each corner. These versions give
you much more control over your object, but you will have to use them very
carefully. It's best to start with a low eRad_default, then add a specific
radius for each point manually. These are the versions you would use if you
were to make, say, 3D fonts from scratch.


The Chamfered Versions

These are like the others, except the bevel is flat.


The Helper Macros

rounded_lprism_cage( pts, z1, z2, lthk )

 * pts  = an array holding the point sets
 * z1   = beginning depth
 * z2   = ending depth
 * lthk = wireframe line thickness 
 
The rounded_lprism_cage macro constructs an unrounded wireframe around your
rounded_lprism objects. pts, z1 and z2 will correspond to the same values
you would pass to the other macros. Is it a useful object for visualizing
your point sets.


rounded_lprism_prism( pts, z1, z2 )

 * pts  = an array holding the point sets
 * z1   = beginning depth
 * z2   = ending depth

This macro will construct a basic linear_spline prism from your point
sets. It can be used to preview your rounded_lprism objects. As before,
pts, z1 and z2 should be the same values you would pass to the other
macros.

If you are making a lot of rounded_lprism objects, your scene will take
longer and longer to parse. To to save on parsing time, you can swap out
your actual rounded_lprism objects for rounded_lprism_prism objects until
a later time, since they parse quickly.

______________
Dos and Don'ts

Don't cross your points over other lines. You can get away with this up
to a certain point, but if you overdo it you are just asking for trouble.

Do keep your beveling smaller than half the distance between the shortest
line segment. If you don't, the object will get confused as it uses off-
set values based on the beveling.

Don't let two consecutive points share the same exact point in space.

Don't let three consecutive points lie along the same plane. You can get
away with it under certain circumstances, but there may be warnings and
geometrical errors.

Do remember to check your points. If you are getting a funky result, the
problem may be with how you wrote your point set.

______
Issues

It cannot always handle very sharp angles. At some point the beveling
will break the object if the angle is too sharp. You'll know this sit-
uation when you come across it.

The rounded_lprism objects cannot be used in CSG operations. It's dis-
appointing, I know, but I strove to make rounded_lprism render as fast
as possible. Instead of using a solid prism as a base, I used polygon
objects to cap the ends. Rather than using costly difference/inter-
section/merge statements for everything, I used clipped_by statements
in their place. To overcome the CSG limitation, punch a hole through the
object using the hole creation methods described previously and fill it
with your CSG object. If that won't fit your needs, you may get by with
cleverly-crafted clipped_by statements, but it may be tricky.

Occasionally you might get dark spots on the rounded corners of an ob-
ject. It ususally happens when the point radius is lower than the amount
of beveling. It doesn't happen all the time, but the chances increase as
the beveling increases. So if bevel is set to 0.1 and you've got spots,
set eRad_default to 0.101. The chamfered versions seem to be OK.

Sometimes other artifacts may occur on the corners when using trans-
parency. There's not much I can do about it right now, but if you lower
your beveling slightly and adjust eRad_default in relation to bevel, you
might be able to get rid of them. The chamfered versions seem to be OK.

There are bound to be even other artifacts that I haven't seen. I expect
that most of these will occur when your object is transparent. Try to
fine-tune your points, depth, radius and beveling if you are getting
weird results.

If you have any questions, comments or bugs to report, write me at
stbenge@hotmail.com

Happy Ray Tracing!