LIBRT(3)
π LIBRT(3) β the BRL-CAD raytracing library, bestie π
okay so this is librt, the library for raytracing an MGED database, and it's giving BRL-CAD main character energy. This manual page is long and it comes in two parts β this is part 1, so settle in πβ¨.
πΈ NAME πΈ
librt β library for raytracing an MGED database. no cap, that's the whole vibe π
.
π¦ SYNOPSIS π¦
Bestie, the source itself is lowkey telling us this file is stale:
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.
So here's the interface as written, exactly as it appears:
#include "vmath.h"
#include "raytrace.h"
extern struct rt_functab OBJ[];
extern struct rt_g rt_g;
struct rt_i *rt_dirbuild(char * mged_file_name, char * buf, int len);
int rt_gettree(struct rt_i * rtip, char * object_name);
void rt_prep(struct rt_i * rtip);
int rt_shootray(struct application * ap);
void rt_prep_timer(void);
doublert_read_timer(char *buf, int len);
void rt_pr_partitions(struct rt_i *rtip struct partition *phead, char *title);
void rt_pr_seg(struct seg *segp);
segp;
struct soltab *rt_find_solid(void);
π DESCRIPTION π
rt_dirbuild opens mged_file_name and builds a directory for quick lookup of objects. It returns a pointer to a struct rt_i on success β often called rtip β or RTI_NULL on failure, like if it literally cannot open the named database π. Save that pointer, because rt_gettree() requires it. The user-supplied buffer buf gets filled with up to len characters of information from the first title record in the database. If you want "air" objects to be reported as "hits" during ray-tracing, set the useair member of the struct rt_i before the first call to rt_gettree().
All objects β groups and regions β that are gonna be included in the description to be raytraced must be preprocessed with rt_gettree(), which returns -1 for failure and 0 for success. You can call this function as many times as you need, bestie. Just be certain to pass the struct rt_i pointer from rt_dirbuild every single time π«Ά.
After the last rt_gettree() call, rt_prep() can be called to complete the preparation of internal data structures. If you don't explicitly call rt_prep(), it gets indirectly invoked by the first use of rt_shootray(). slay, lazy but functional β¨.
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). that's the whole checklist, no skipping π
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. timing tea βπ
.
bu_bomb can be used to exit your program with msg printed on the standard error output.
π WARNING π
Librt is designed to run in parallel on some multiprocessor machines. On some such machines system calls must be semaphore protected. that's a real one, bestie π³.
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.
π EXIT CODE π
All truly fatal errors detected by the library use bu_bomb to exit with a status of 12. dramatic? maybe. accurate? yes π
.
π DEFINITION π
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. yes, that spelling is in the original, and we respect the iconique typo π.
π₯ DISCUSSION π₯
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). iykyk, macros are the moment π§.
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. grid goals β¨.
πΈ EXAMPLE πΈ
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. the Architecture Librarie(s) situation is:
- 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 */
}
π«Ά SEE ALSO π«Ά
mged(1B), rt(1B).
π DIAGNOSTICS π
"rt_malloc: malloc failure"β if librt is unable to allocate memory withmalloc.`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 trapsSIGFPE, butSIGFPEelsewhere is unexpected.)"rt_shootray: zero length dir vector"β when thea_ray.r_dirvector 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 callingrt_prep()(or after firing the first ray)."rt_prep: re-invocation"β whenrt_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. endianness drama, but make it iconic π¦.
π BUGS π (yes, this section is literally called bugs, buckle up)
okay so there's this one very specific, very vintage situation, and it's giving "legacy hardware moment" π
- On a VAX, the rootfinder detects "hard" cases by taking a
SIGFPEand retrying with a slower but more stable algorithm. bestie. that's the whole sentence. that's the coping mechanism.
and the manpage's official editorial position on this? "This is unfortunate." π that's it, that's the whole review, the authors said what they said and honestly? valid. iconic level of honesty fr fr. no cap, it's literally the most relatable line in the entire page.
π AUTHOR π
BRL-CAD Team β that's the whole credit, a whole team, absolute main character energy, we stan ππ«Ά
π COPYRIGHT π
okay so legal stuff, but make it cute (and also keep it exactly right because it's law, not a vibe):
This software is Copyright (c) 1986-2026 United States Government as represented by the U.S. Army Research Laboratory.
like, the entire U.S. Government, represented by the U.S. Army Research Laboratory, since 1986 and running all the way to 2026. that's a long-term commitment, we love a stable relationship πβ¨
π BUG REPORTS π
found a bug? a problem? a little gremlin in the code? ππ don't suffer in silence, bestie:
- Reports of bugs or problems should be submitted via electronic mail to
devs@brlcad.org
that's it, that's the address, go tell them, they literally asked π«Άπ
aaaand that's a wrap on LIBRT(3) π you made it to the end, I'm so proud of you π₯Ήβ¨ this page came to you courtesy of BRL-CAD, sitting pretty in the LIBRT(3) slot of your manual β go forth and rootfind responsibly, and remember: if you're on a VAX and you catch a SIGFPE, it's not a bug, it's a feature, and it is, in the official words of the documentation, unfortunate ππΈπ¦
π¦ where this page comes from
- nixpkgs unstable: brlcad 7.44.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms