librt — library for raytracing an MGED database
This file seems to be out of date with the sources. Consult the headers for up-to-date information. Use the below interface documentation at your own discretion.
#include "vmath.h" #include "raytrace.h" extern struct rt_functab OBJ[]; extern struct rt_g rt_g;
struct fsfuncrt_i *rt_dirbuild( | mged_file_name, | |
buf, | ||
len) ; |
char * mged_file_name
;char * buf
;int len
;int fsfuncrt_gettree( | rtip, | |
object_name) ; |
struct rt_i * rtip
;char * object_name
;void fsfuncrt_prep( | rtip) ; |
struct rt_i * rtip
;int fsfuncrt_shootray( | ap) ; |
struct application * ap
;void fsfuncrt_prep_timer( | ) ; |
doublefsfuncrt_read_timer( | buf, | |
len) ; |
char *buf
;int len
;void fsfuncrt_pr_partitions( | phead, | |
title) ; |
struct rt_i *rtip struct partition *phead
;char *title
;void fsfuncrt_pr_seg( | segp) ; |
struct seg *segp
;segp;
struct fsfuncsoltab *rt_find_solid( | ) ; |
rt_dirbuild
opens
mged_file_name
and builds a directory for quick lookup of objects.
rt_dirbuild
returns a pointer to a
struct rt_i
on success (often called ``rtip
''),
or
RTI_NULL
on failure (such as being unable to open the named database).
This pointer must be saved, as it is a required parameter to
rt_gettree
.
The user-supplied buffer
buf
is filled with up to
len
characters
of information from the first title record in the database.
If it is desired for "air" objects to be reported as "hits"
during ray-tracing, then the
useair
member of the
struct rt_i
must be set before the first call to
rt_gettree
.
All objects (groups and regions) which are to be included in the description
to be raytraced must be preprocessed with
rt_gettree
,
which returns -1 for failure and 0 for success.
This function can be called as many times as required.
Be certain to pass the
struct rt_i
pointer from
rt_dirbuild
each time.
After the last
rt_gettree
call,
rt_prep
can be called to complete the preparation of internal data structures.
If
rt_prep
is not explicitly called, it will be indirectly invoked by the first use of
rt_shootray
.
To fire a ray at the model, an
application
structure must be
prepared and its address passed to
rt_shootray
.
Note that it is mandatory that you provide values for
a_ray.r_pt
(the starting point of the ray to be fired),
a_ray.r_dir
(a unit-length direction vector),
a_hit
(address of user-supplied hit routine),
a_miss
(address of user-supplied miss routine),
a_overlap
(address of user-supplied overlap routine; may be null),
a_rt_i
(struct rt_i pointer, from
rt_dirbuild),
a_onehit
(flag controlling stop after first hit),
a_level
(recursion level, just for diagnostic printing),
and
a_resource
(address of
resource
structure; may be null).
To obtain a report of CPU usage for a portion or portions of your program,
frame the statements with calls to
rt_prep_timer
and
rt_read_timer
.
Each call to
rt_prep_timer
resets the timing process, after which
rt_read_timer
can be called to get
a double which is the elapsed CPU time in seconds since
rt_prep_timer
was last called.
In addition, up to
len
bytes of
system-specific detailing of resource consumption
is placed in the user-supplied buffer
buf
.
bu_bomb can be used to exit your program with msg printed on the standard error output.
Librt is designed to run in parallel on some multiprocessor machines. On some such machines system calls must be semaphore protected.
Dynamic memory handling in applications using librt should use the functions provided by libbu instead of the usual system runtime library routines. The libbu versions do not return to the caller unless they succeed. If they fail, they call bu_bomb with their last argument (str) as the parameter. The string parameter usually indicates the purpose of the memory being allocated.
RPP - Rectangular ParallelePiped. A region of space defined by minimum and maximum values in X, Y, and Z. RPPs are used by librt as bounding volumes for solids.
You should study the structures in
raytrace.h,
in particular, the
application
structure,
the
partition
structure and its component structures to get an idea of what information
is handed to/from
rt_shootray
.
rt_shootray
may be called recursively from your
a_hit
routine (good for doing bounced rays).
If you only care about the first
object hit along the path of the ray, set the
a_onehit
flag in the application structure before calling
rt_shootray
.
rt_shootray
returns the return value of the user-supplied hit or miss function
that it called.
If the ray intersects the model, the
a_hit
routine is called
with a pointer to the application structure and a pointer to a
linked list of ray partitions
(struct partition).
Within each partition are
seg
(solid segment)
and
hit
(intersection with evaluated region)
structure pointers
for the places where the ray enters and leaves this partition of space.
pt_inhit.hit_dist
is the parametric distance at which the ray enters
the partition, and
pt_outhit.hit_dist
is the parametric distance at which the ray leaves.
Note that while the
hit
structure contains
hit_point
and
hit_norm
elements, they are not computed by
rt_shootray
.
If these are needed, they can be filled in by using the
RT_HIT_NORMAL
macro;
if surface curvature information is needed,
it can be obtained by using the
RT_CURVE
macro after
RT_HIT_NORMAL;
if only the
hit_point
is needed,
it can be filled in by using the
VJOIN1
macro (see the following example).
If the ray contains any overlaps (partitions claimed by two or more regions) the a_overlap routine is called for each such partition with pointers to the application structure, the overlap partition, two regions, and the remaining partitions along the ray. If the a_overlap member is null, librt uses a default overlap handler. Additionally, librt provides the routine
If the ray does not intersect the model, the a_miss routine is called with a pointer to the application structure.
Helpful in generating a grid of ray origins, the bounding RPP of the
model is computed by
rt_gettree
and is stored in
rtip->mdl_min
and
rtip->mdl_max.
A program can be loaded as follows:
$ cc -I/usr/brlcad/include main.c /usr/brlcad/lib/librt.a -l<system-specific> -lm
where <system-specific> indicates libraries required on a particular architecture. The table below indicates which system specific libraries are necessary on a particular architecture.
Architecture Librarie(s) Alliant FX/8 -lcvec -lcommon Alliant FX/2800 -lcommon SGI 4D -lmpc Cray(X/Y) -L/lib/multi -lu -lio Cray2 -lmt Encore Multi-Max -lpp
Here is a portion of a hypothetical program which uses the library:
#include <vmath.h>
#include <raytrace.h>
int
main(int argc, char argv[])
{
static int do_if_hit(), do_if_miss(); /* Application routines */
register int h, v;
int grid_sz;
struct application ap; /* Set up for rt_shootray() */
struct rt_i *rtip;
/* ... */
/* Build the directory. */
rtip = rt_dirbuild( argv[bu_optind++] );
/* Load the desired portion of the model. */
while (argv[bu_optind] != NULL)
rt_gettree(rtip, argv[bu_optind++]);
ap.a_hit = do_if_hit; /* Routine for hit */
ap.a_miss = do_if_missed; /* Routine for miss */
ap.a_overlap = 0;
ap.a_rt_i = rtip;
ap.a_level = 0;
ap.a_onehit = 0; /* Return all objects along ray */
ap.a_resource = 0;
for (v = 0; v < grid_sz; ++v) /* For each scanline */
for (h = 0; h < grid_sz; ++h) {
/* Set up ray origin. */
VMOVE( ap.a_ray.r_pt, get_grid(h, v));
/* Compute ray direction. */
VMOVE( ap.a_ray.r_dir, get_dir(h, v));
/* Must be unit vector. */
VUNITIZE(ap.a_ray.r_dir);
(void)rt_shootray(&ap);
}
/* ... */
}
static int
do_if_hit(register struct application *ap,
struct partition *PartHeadp)
{
extern void put_component();
struct curvature incurv;
register struct partition *pp;
for (pp = PartHeadp->pt_forw; pp != PartHeadp;
pp = pp->pt_forw) {
/* Fill in all inhit info, but just the exit location for outhit. */
RT_HIT_NORMAL(pp->pt_inhit->hit_normal, pp->pt_inhit,
pp->pt_inseg->seg_stp, &ap->a_ray,
pp->pt_inflip);
RT_CURVE(&incurv, pp->pt_inhit, pp->pt_inseg->seg_stp);
VJOIN1(pp->pt_outhit->hit_point, ap->a_ray.r_pt,
pp->pt_outhit->hit_dist, ap->a_ray.r_dir);
/* Do something based on information in partition structure
* such as output a shotline component data record.
*/
put_component( pp->pt_inhit, &incurv, pp->pt_outhit );
/* ... */
}
return 1; /* Report hit to main routine */
}
static int
do_if_missed(register struct application *ap)
{
return 0; /* Report miss to main routine */
}
"rt_malloc: malloc failure",
if
librt
is unable to allocate memory with
malloc.
``rt_???: read error'', if an error or EOF occurs while
reading from the model database.
"unexpected SIGFPE!" when a floating point error occurs.
(The rootfinder traps SIGFPE, but SIGFPE elsewhere is unexpected.)
"rt_shootray: zero length dir vector" when the
a_ray.r_dir
vector is not unit length.
"rt_gettree called again after rt_prep!" when an attempt is made
to add more sub-trees to the active model after calling
rt_prep
(or after firing the first ray).
"rt_prep: re-invocation" when
rt_prep
is called more than once.
"rt_prep: no solids to prep" when there are no valid solids
in the model.
The LIBRT_DEBUG environment variable may be set to the hexadecimal bit vector as described by the DEBUG_* flags listed in the raytrace.h header. Similarly, many LIBRT applications provide a "-x #" command-line option which will take precedence over the environment variable.
The LIBRT_V4FLIP environment variable may be set to a true or false value to respectively force or disable endianness interpretation of v4 geometry database files. The default behavior is to automatically detect whether flipping the endian interpretation will help LIBRT read a binary-incompatible v4 geometry database file. Setting LIBRT_V4FLIP will override automatic detection.
The LIBRT_BOT_MINTIE environment variable may be set to the minimum number of faces a BoT primitive must have to exercise the Triangle Intersection Engine (TIE) raytrace evaluation. A value less than or equal to zero will utilize traditional BoT raytracing instead of TIE.
On a VAX, the rootfinder detects "hard" cases by taking a SIGFPE and retrying with a slower but more stable algorithm. This is unfortunate.