LIBRT(3)

NAME
librt - library for raytracing an MGED database

SYNOPSIS
#include "machine.h"
#include "vmath.h"
#include "raytrace.h"

extern struct rt_functab rt_functab[];
extern struct rt_g rt_g;

struct rt_i *rt_dirbuild( mged_file_name, buf, len )
char *mged_file_name;
char *buf;
int len;

int rt_gettree( rtip, object_name )
struct rt_i *rtip;
char *object_name;

void rt_prep( rtip )
struct rt_i *rtip;

int rt_shootray( ap )
struct application *ap;

void rt_prep_timer()

double rt_read_timer( buf, len )
char *buf;
int len;

void rt_pr_partitions( rtip, phead, title )
struct rt_i *rtip
struct partition *phead;
char *title;

void rt_pr_seg( segp );
struct seg *segp;

void rt_bomb( msg )
char *msg;

void rt_log( fmt, ... )
char *fmt;

char *rt_malloc(cnt, str)
unsigned int cnt;
char *str;

void rt_free(ptr, str)
char *ptr;
char *str;

char *rt_realloc(ptr, cnt, str)
register char   *ptr;
unsigned int    cnt;
char      *str;

char *rt_calloc( nelem, elsize, str )
unsigned int    nelem;
unsigned int    elsize;
char      *str;

void rt_prmem(str)
char *str;

char *rt_strdup( cp )
char *cp;

struct soltab *rt_find_solid()

void MAT_ZERO( m )			/* fill matrix m with zeros */
matp_t m;

void MAT_IDN( m )			/* fill matrix m with identity matrix */
matp_t m;

void MAT_COPY( o, i )		/* copy matrix i to matrix o */
matp_t o, i;

void mat_mul( o, i1, i2 )		/* multiply i1 by i2 and store in o */
matp_t o, i1, i2;

void matXvec( ov, m, iv )		/* multiply m by vector iv, store in ov */
matp_t ov, m, iv;

void mat_inv( o, i )			/* invert matrix i, store result in o */
matp_t o, i;

void mat_print( title, m )		/* print matrix m, (with title) on stdout */
char *title;
matp_t m;

void mat_trn( o, i )			/* transpose matrix i into matrix o */
matp_t o, i;

void mat_ae( o, a, e )		/* rotation matrix o from azimuth+elevation */
matp_t o;
double a, e;

void mat_angles( o, a, b, g )	/* rotation matrix o from angles a, b, g */
matp_t o;
double a, b, g;

void vtoh_move( v, h )		/* homogeneous vector from ordinary vector */
vectp_t v, h;

void htov_move( h, v )		/* ordinary vector from homogeneous vector */
vectp_t h, v;

DESCRIPTION
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.

rt_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. For this reason, librt provides:

rt_log()
rt_malloc() rt_free() rt_calloc() rt_realloc() rt_prmem()
rt_strdup()

The fuction rt_log() is essentially a semaphore-protected version of printf() except that it uses the standard error (stderr) instead of the standard output (stdout).

Dynamic memory handling in applications using librt should use the functions provided by librt instead of the usual system runtime library routines. The librt versions do not return to the caller unless they succeed. If they fail, they call rt_bomb with their last argument (str) as the parameter. The string parameter usually indicates the purpose of the memory being allocated.

The fuction rt_strdup() calls rt_malloc() instead of malloc() to acquire memory. Thus it should be used in place of strdup() in programs linking with librt.

EXIT CODE
All truly fatal errors detected by the library use rt_bomb to exit with a status of 12.

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.

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_NORM macro; if surface curvature information is needed, it can be obtained by using the RT_CURVE macro after RT_HIT_NORM; 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 rt_overlap_quietly which behaves exactly as the default handler, excepting that it produces no warning messages on standard error.

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.

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 particluar architecture. The table below indicates which system specific libraries are necesary 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 <machine.h>
    #include <vmath.h>
    #include <raytrace.h>
    main( argc, argv )
    int argc;
    char *argv[];
    {
    	extern int optind;			/* Used by getopt(3C) */
    	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[optind++] );
    	/* Load the desired portion of the model. */
    	while( argv[optind] != NULL )
    		rt_gettree( rtip, argv[optind++] );
    	ap.a_hit = do_if_hit;		/* Supply routine for hit */
    	ap.a_miss = do_if_missed;	/* Supply 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( ap, PartHeadp )
    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_NORM( pp->pt_inhit, pp->pt_inseg->seg_stp, &ap->a_ray );
    		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 );
    		/* Check for flipped normal and fix (if you intend to use it). */
    		if( pp->pt_inflip )  {
    			VREVERSE( pp->pt_inhit->hit_normal,
    					pp->pt_inhit->hit_normal );
    			pp->pt_inflip = 0;
    		}
    		/* 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( ap )
    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 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.

AUTHOR(S)
Michael John Muuss

BUGS
On a VAX, the rootfinder detects ``hard'' cases by taking a SIGFPE and retrying with a slower but more stable algorithm. This is unfortunate.

SOURCE
 SECAD/VLD Computing Consortium, Bldg 394
 The U. S. Army Ballistic Research Laboratory
 Aberdeen Proving Ground, Maryland 21005

COPYRIGHT
This software is Copyright (c) 1985-2006 United States Government as represented by the U.S. Army Research Laboratory. All rights reserved.

BUG REPORTS
Reports of bugs or problems should be submitted via electronic mail to <devs@brlcad.org>.