bundle.c

Go to the documentation of this file.
00001 /*                        B U N D L E . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1985-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 
00022 /** @addtogroup librt */
00023 /*@{*/
00024 /** @file bundle.c
00025  *
00026  * NOTE:  This is experimental code right now.
00027  *
00028  *  Author -
00029  *      Michael John Muuss
00030  *
00031  *  Source -
00032  *      SECAD/VLD Computing Consortium, Bldg 394
00033  *      The U. S. Army Ballistic Research Laboratory
00034  *      Aberdeen Proving Ground, Maryland  21005
00035  *
00036  */
00037 /*@}*/
00038 
00039 #ifndef lint
00040 static const char RCSbundle[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/bundle.c,v 14.11 2006/09/16 02:04:24 lbutler Exp $ (BRL)";
00041 #endif
00042 
00043 #include "common.h"
00044 
00045 
00046 
00047 #include <stdio.h>
00048 #include <math.h>
00049 #include "machine.h"
00050 #include "vmath.h"
00051 #include "bu.h"
00052 #include "bn.h"
00053 #include "raytrace.h"
00054 #include "./debug.h"
00055 
00056 extern void     rt_plot_cell(const union cutter *cutp, struct rt_shootray_status *ssp, struct bu_list *waiting_segs_hd, struct rt_i *rtip);
00057 
00058 /*
00059  *                      R T _ F I N D _ N U G R I D
00060  *
00061  *  Along the given axis, find which NUgrid cell this value lies in.
00062  *  Use method of binary subdivision.
00063  */
00064 extern int      rt_find_nugrid(struct nugridnode *nugnp, int axis, fastf_t val);
00065 
00066 
00067 /*
00068  *                      R T _ A D V A N C E _ T O _ N E X T _ C E L L
00069  */
00070 extern const union cutter *rt_advance_to_next_cell(register struct rt_shootray_status *ssp);
00071 
00072 /*
00073  *                      R T _ S H O O T R A Y _ B U N D L E
00074  *
00075  *  Note that the direction vector r_dir
00076  *  must have unit length;  this is mandatory, and is not ordinarily checked,
00077  *  in the name of efficiency.
00078  *
00079  *  Input:  Pointer to an application structure, with these mandatory fields:
00080  *      a_ray.r_pt      Starting point of ray to be fired
00081  *      a_ray.r_dir     UNIT VECTOR with direction to fire in (dir cosines)
00082  *      a_hit           Routine to call when something is hit
00083  *      a_miss          Routine to call when ray misses everything
00084  *
00085  *  Calls user's a_miss() or a_hit() routine as appropriate.
00086  *  Passes a_hit() routine list of partitions, with only hit_dist
00087  *  fields valid.  Normal computation deferred to user code,
00088  *  to avoid needless computation here.
00089  *
00090  *  Formal Return: whatever the application function returns (an int).
00091  *
00092  *  NOTE:  The appliction functions may call rt_shootray() recursively.
00093  *      Thus, none of the local variables may be static.
00094  *
00095  *  To prevent having to lock the statistics variables in a PARALLEL
00096  *  environment, all the statistics variables have been moved into
00097  *  the 'resource' structure, which is allocated per-CPU.
00098  */
00099 
00100 /* XXX maybe parameter with NORM, UV, CURVE bits? */
00101 
00102 int
00103 rt_shootray_bundle(register struct application *ap, struct xray *rays, int nrays)
00104 {
00105         struct rt_shootray_status       ss;
00106         struct seg              new_segs;       /* from solid intersections */
00107         struct seg              waiting_segs;   /* awaiting rt_boolweave() */
00108         struct seg              finished_segs;  /* processed by rt_boolweave() */
00109         fastf_t                 last_bool_start;
00110         struct bu_bitv          *solidbits;     /* bits for all solids shot so far */
00111         struct bu_ptbl          *regionbits;    /* table of all involved regions */
00112         char                    *status;
00113         auto struct partition   InitialPart;    /* Head of Initial Partitions */
00114         auto struct partition   FinalPart;      /* Head of Final Partitions */
00115         struct soltab           **stpp;
00116         register const union cutter *cutp;
00117         struct resource         *resp;
00118         struct rt_i             *rtip;
00119         const int               debug_shoot = RT_G_DEBUG & DEBUG_SHOOT;
00120 
00121         RT_AP_CHECK(ap);
00122         if( ap->a_magic )  {
00123                 RT_CK_AP(ap);
00124         } else {
00125                 ap->a_magic = RT_AP_MAGIC;
00126         }
00127         if( ap->a_ray.magic )  {
00128                 RT_CK_RAY(&(ap->a_ray));
00129         } else {
00130                 ap->a_ray.magic = RT_RAY_MAGIC;
00131         }
00132         if( ap->a_resource == RESOURCE_NULL )  {
00133                 ap->a_resource = &rt_uniresource;
00134                 rt_uniresource.re_magic = RESOURCE_MAGIC;
00135                 if(RT_G_DEBUG)bu_log("rt_shootray_bundle:  defaulting a_resource to &rt_uniresource\n");
00136         }
00137         ss.ap = ap;
00138         rtip = ap->a_rt_i;
00139         RT_CK_RTI( rtip );
00140         resp = ap->a_resource;
00141         RT_CK_RESOURCE(resp);
00142         ss.resp = resp;
00143 
00144         if(RT_G_DEBUG&(DEBUG_ALLRAYS|DEBUG_SHOOT|DEBUG_PARTITION|DEBUG_ALLHITS)) {
00145                 bu_log_indent_delta(2);
00146                 bu_log("\n**********shootray_bundle cpu=%d  %d,%d lvl=%d (%s)\n",
00147                         resp->re_cpu,
00148                         ap->a_x, ap->a_y,
00149                         ap->a_level,
00150                         ap->a_purpose != (char *)0 ? ap->a_purpose : "?" );
00151                 bu_log("Pnt (%g, %g, %g) a_onehit=%d\n",
00152                         V3ARGS(ap->a_ray.r_pt),
00153                         ap->a_onehit );
00154                 VPRINT("Dir", ap->a_ray.r_dir);
00155         }
00156         if(RT_BADVEC(ap->a_ray.r_pt)||RT_BADVEC(ap->a_ray.r_dir))  {
00157                 bu_log("\n**********shootray cpu=%d  %d,%d lvl=%d (%s)\n",
00158                         resp->re_cpu,
00159                         ap->a_x, ap->a_y,
00160                         ap->a_level,
00161                         ap->a_purpose != (char *)0 ? ap->a_purpose : "?" );
00162                 VPRINT(" r_pt", ap->a_ray.r_pt);
00163                 VPRINT("r_dir", ap->a_ray.r_dir);
00164                 rt_bomb("rt_shootray_bundle() bad ray\n");
00165         }
00166 
00167         if( rtip->needprep )
00168                 rt_prep(rtip);
00169 
00170         InitialPart.pt_forw = InitialPart.pt_back = &InitialPart;
00171         InitialPart.pt_magic = PT_HD_MAGIC;
00172         FinalPart.pt_forw = FinalPart.pt_back = &FinalPart;
00173         FinalPart.pt_magic = PT_HD_MAGIC;
00174         ap->a_Final_Part_hdp = &FinalPart;
00175 
00176         BU_LIST_INIT( &new_segs.l );
00177         BU_LIST_INIT( &waiting_segs.l );
00178         BU_LIST_INIT( &finished_segs.l );
00179         ap->a_finished_segs_hdp = &finished_segs;
00180 
00181         if( BU_LIST_UNINITIALIZED( &resp->re_parthead ) )  {
00182                 /* XXX This shouldn't happen any more */
00183                 bu_log("rt_shootray_bundle() resp=x%x uninitialized, fixing it\n", resp);
00184                 /*
00185                  *  We've been handed a mostly un-initialized resource struct,
00186                  *  with only a magic number and a cpu number filled in.
00187                  *  Init it and add it to the table.
00188                  *  This is how application-provided resource structures
00189                  *  are remembered for later cleanup by the library.
00190                  */
00191                 rt_init_resource( resp, resp->re_cpu, rtip );
00192 
00193                 /* Ensure that this CPU's resource structure is registered */
00194                 BU_ASSERT_PTR( BU_PTBL_GET(&rtip->rti_resources, resp->re_cpu), !=, NULL );
00195         }
00196 
00197         solidbits = get_solidbitv( rtip->nsolids, resp );
00198         bu_bitv_clear(solidbits);
00199 
00200         if( BU_LIST_IS_EMPTY( &resp->re_region_ptbl ) )  {
00201                 BU_GETSTRUCT( regionbits, bu_ptbl );
00202                 bu_ptbl_init( regionbits, 7, "rt_shootray_bundle() regionbits ptbl" );
00203         } else {
00204                 regionbits = BU_LIST_FIRST( bu_ptbl, &resp->re_region_ptbl );
00205                 BU_LIST_DEQUEUE( &regionbits->l );
00206                 BU_CK_PTBL(regionbits);
00207         }
00208 
00209         /* Verify that direction vector has unit length */
00210         if(RT_G_DEBUG) {
00211                 FAST fastf_t f, diff;
00212                 f = MAGSQ(ap->a_ray.r_dir);
00213                 if( NEAR_ZERO(f, 0.0001) )  {
00214                         rt_bomb("rt_shootray_bundle:  zero length dir vector\n");
00215                         return(0);
00216                 }
00217                 diff = f - 1;
00218                 if( !NEAR_ZERO( diff, 0.0001 ) )  {
00219                         bu_log("rt_shootray_bundle: non-unit dir vect (x%d y%d lvl%d)\n",
00220                                 ap->a_x, ap->a_y, ap->a_level );
00221                         f = 1/f;
00222                         VSCALE( ap->a_ray.r_dir, ap->a_ray.r_dir, f );
00223                 }
00224         }
00225 
00226         /* Compute the inverse of the direction cosines */
00227         if( ap->a_ray.r_dir[X] < -SQRT_SMALL_FASTF )  {
00228                 ss.abs_inv_dir[X] = -(ss.inv_dir[X]=1.0/ap->a_ray.r_dir[X]);
00229                 ss.rstep[X] = -1;
00230         } else if( ap->a_ray.r_dir[X] > SQRT_SMALL_FASTF )  {
00231                 ss.abs_inv_dir[X] =  (ss.inv_dir[X]=1.0/ap->a_ray.r_dir[X]);
00232                 ss.rstep[X] = 1;
00233         } else {
00234                 ap->a_ray.r_dir[X] = 0.0;
00235                 ss.abs_inv_dir[X] = ss.inv_dir[X] = INFINITY;
00236                 ss.rstep[X] = 0;
00237         }
00238         if( ap->a_ray.r_dir[Y] < -SQRT_SMALL_FASTF )  {
00239                 ss.abs_inv_dir[Y] = -(ss.inv_dir[Y]=1.0/ap->a_ray.r_dir[Y]);
00240                 ss.rstep[Y] = -1;
00241         } else if( ap->a_ray.r_dir[Y] > SQRT_SMALL_FASTF )  {
00242                 ss.abs_inv_dir[Y] =  (ss.inv_dir[Y]=1.0/ap->a_ray.r_dir[Y]);
00243                 ss.rstep[Y] = 1;
00244         } else {
00245                 ap->a_ray.r_dir[Y] = 0.0;
00246                 ss.abs_inv_dir[Y] = ss.inv_dir[Y] = INFINITY;
00247                 ss.rstep[Y] = 0;
00248         }
00249         if( ap->a_ray.r_dir[Z] < -SQRT_SMALL_FASTF )  {
00250                 ss.abs_inv_dir[Z] = -(ss.inv_dir[Z]=1.0/ap->a_ray.r_dir[Z]);
00251                 ss.rstep[Z] = -1;
00252         } else if( ap->a_ray.r_dir[Z] > SQRT_SMALL_FASTF )  {
00253                 ss.abs_inv_dir[Z] =  (ss.inv_dir[Z]=1.0/ap->a_ray.r_dir[Z]);
00254                 ss.rstep[Z] = 1;
00255         } else {
00256                 ap->a_ray.r_dir[Z] = 0.0;
00257                 ss.abs_inv_dir[Z] = ss.inv_dir[Z] = INFINITY;
00258                 ss.rstep[Z] = 0;
00259         }
00260 
00261         /*
00262          *  If ray does not enter the model RPP, skip on.
00263          *  If ray ends exactly at the model RPP, trace it.
00264          */
00265         if( !rt_in_rpp( &ap->a_ray, ss.inv_dir, rtip->mdl_min, rtip->mdl_max )  ||
00266             ap->a_ray.r_max < 0.0 )  {
00267                 resp->re_nmiss_model++;
00268                 ap->a_return = ap->a_miss( ap );
00269                 status = "MISS model";
00270                 goto out;
00271         }
00272 
00273         /*
00274          *  The interesting part of the ray starts at distance 0.
00275          *  If the ray enters the model at a negative distance,
00276          *  (ie, the ray starts within the model RPP),
00277          *  we only look at little bit behind (BACKING_DIST) to see if we are
00278          *  just coming out of something, but never further back than
00279          *  the intersection with the model RPP.
00280          *  If the ray enters the model at a positive distance,
00281          *  we always start there.
00282          *  It is vital that we never pick a start point outside the
00283          *  model RPP, or the space partitioning tree will pick the
00284          *  wrong box and the ray will miss it.
00285          *
00286          *  BACKING_DIST should probably be determined by floating point
00287          *  noise factor due to model RPP size -vs- number of bits of
00288          *  floating point mantissa significance, rather than a constant,
00289          *  but that is too hideous to think about here.
00290          *  Also note that applications that really depend on knowing
00291          *  what region they are leaving from should probably back their
00292          *  own start-point up, rather than depending on it here, but
00293          *  it isn't much trouble here.
00294          */
00295         ss.box_start = ss.model_start = ap->a_ray.r_min;
00296         ss.box_end = ss.model_end = ap->a_ray.r_max;
00297 
00298         if( ss.box_start < BACKING_DIST )
00299                 ss.box_start = BACKING_DIST; /* Only look a little bit behind */
00300 
00301         ss.lastcut = CUTTER_NULL;
00302         ss.old_status = (struct rt_shootray_status *)NULL;
00303         ss.curcut = &ap->a_rt_i->rti_CutHead;
00304         if( ss.curcut->cut_type == CUT_NUGRIDNODE ) {
00305                 ss.lastcell = CUTTER_NULL;
00306                 VSET( ss.curmin, ss.curcut->nugn.nu_axis[X][0].nu_spos,
00307                                  ss.curcut->nugn.nu_axis[Y][0].nu_spos,
00308                                  ss.curcut->nugn.nu_axis[Z][0].nu_spos );
00309                 VSET( ss.curmax, ss.curcut->nugn.nu_axis[X][ss.curcut->nugn.nu_cells_per_axis[X]-1].nu_epos,
00310                                  ss.curcut->nugn.nu_axis[Y][ss.curcut->nugn.nu_cells_per_axis[Y]-1].nu_epos,
00311                                  ss.curcut->nugn.nu_axis[Z][ss.curcut->nugn.nu_cells_per_axis[Z]-1].nu_epos );
00312         } else if( ss.curcut->cut_type == CUT_CUTNODE ||
00313                    ss.curcut->cut_type == CUT_BOXNODE ) {
00314                 ss.lastcell = ss.curcut;
00315                 VMOVE( ss.curmin, rtip->mdl_min );
00316                 VMOVE( ss.curmax, rtip->mdl_max );
00317         }
00318 
00319         last_bool_start = BACKING_DIST;
00320         ss.newray = ap->a_ray;          /* struct copy */
00321         ss.odist_corr = ss.obox_start = ss.obox_end = -99;
00322         ss.dist_corr = 0.0;
00323 
00324         /*
00325          *  While the ray remains inside model space,
00326          *  push from box to box until ray emerges from
00327          *  model space again (or first hit is found, if user is impatient).
00328          *  It is vitally important to always stay within the model RPP, or
00329          *  the space partitoning tree will pick wrong boxes & miss them.
00330          */
00331         while( (cutp = rt_advance_to_next_cell( &ss )) != CUTTER_NULL )  {
00332                 if(debug_shoot) {
00333                         rt_pr_cut( cutp, 0 );
00334                 }
00335 
00336                 if( cutp->bn.bn_len <= 0 )  {
00337                         /* Push ray onwards to next box */
00338                         ss.box_start = ss.box_end;
00339                         resp->re_nempty_cells++;
00340                         continue;
00341                 }
00342 
00343                 /* Consider all objects within the box */
00344                 stpp = &(cutp->bn.bn_list[cutp->bn.bn_len-1]);
00345                 for( ; stpp >= cutp->bn.bn_list; stpp-- )  {
00346                         register struct soltab *stp = *stpp;
00347                         int ray;
00348 
00349                         if( BU_BITTEST( solidbits, stp->st_bit ) )  {
00350                                 resp->re_ndup++;
00351                                 continue;       /* already shot */
00352                         }
00353 
00354                         /* Shoot all the rays in the bundle through this solid */
00355                         /* XXX open issue: entering neighboring cells too? */
00356                         BU_BITSET( solidbits, stp->st_bit );
00357 
00358                         for( ray=0; ray < nrays; ray++ )  {
00359                                 struct xray     ss2_newray;
00360 
00361                                 /* Be compatible with the ss backing distance stuff */
00362                                 VMOVE( ss2_newray.r_dir, rays[ray].r_dir );
00363                                 VJOIN1( ss2_newray.r_pt, rays[ray].r_pt, ss.dist_corr, ss2_newray.r_dir );
00364 
00365                                 /* Check against bounding RPP, if desired by solid */
00366                                 if( rt_functab[stp->st_id].ft_use_rpp )  {
00367                                         if( !rt_in_rpp( &ss2_newray, ss.inv_dir,
00368                                             stp->st_min, stp->st_max ) )  {
00369                                                 if(debug_shoot)bu_log("rpp miss %s by ray %d\n", stp->st_name, ray);
00370                                                 resp->re_prune_solrpp++;
00371                                                 continue;       /* MISS */
00372                                         }
00373                                         if( ss.dist_corr + ss2_newray.r_max < BACKING_DIST )  {
00374                                                 if(debug_shoot)bu_log("rpp skip %s, dist_corr=%g, r_max=%g, by ray %d\n", stp->st_name, ss.dist_corr, ss2_newray.r_max, ray);
00375                                                 resp->re_prune_solrpp++;
00376                                                 continue;       /* MISS */
00377                                         }
00378                                 }
00379 
00380                                 if(debug_shoot)bu_log("shooting %s with ray %d\n", stp->st_name, ray);
00381                                 resp->re_shots++;
00382                                 BU_LIST_INIT( &(new_segs.l) );
00383                                 if( rt_functab[stp->st_id].ft_shot(
00384                                     stp, &ss2_newray, ap, &new_segs ) <= 0 )  {
00385                                         resp->re_shot_miss++;
00386                                         continue;       /* MISS */
00387                                 }
00388 
00389                                 /* Add seg chain to list awaiting rt_boolweave() */
00390                                 {
00391                                         register struct seg *s2;
00392                                         while(BU_LIST_WHILE(s2,seg,&(new_segs.l)))  {
00393                                                 BU_LIST_DEQUEUE( &(s2->l) );
00394                                                 /* Restore to original distance */
00395                                                 s2->seg_in.hit_dist += ss.dist_corr;
00396                                                 s2->seg_out.hit_dist += ss.dist_corr;
00397                                                 s2->seg_in.hit_rayp = s2->seg_out.hit_rayp = &rays[ray];
00398                                                 BU_LIST_INSERT( &(waiting_segs.l), &(s2->l) );
00399                                         }
00400                                 }
00401                                 resp->re_shot_hit++;
00402                                 break;                  /* HIT */
00403                         }
00404                 }
00405                 if( RT_G_DEBUG & DEBUG_ADVANCE )
00406                         rt_plot_cell( cutp, &ss, &(waiting_segs.l), rtip);
00407 
00408                 /*
00409                  *  If a_onehit == 0 and a_ray_length <= 0, then the ray
00410                  *  is traced to +infinity.
00411                  *
00412                  *  If a_onehit != 0, then it indicates how many hit points
00413                  *  (which are greater than the ray start point of 0.0)
00414                  *  the application requires, ie, partitions with inhit >= 0.
00415                  *  (If negative, indicates number of non-air hits needed).
00416                  *  If this box yielded additional segments,
00417                  *  immediately weave them into the partition list,
00418                  *  and perform final boolean evaluation.
00419                  *  If this results in the required number of final
00420                  *  partitions, then cease ray-tracing and hand the
00421                  *  partitions over to the application.
00422                  *  All partitions will have valid in and out distances.
00423                  *  a_ray_length is treated similarly to a_onehit.
00424                  */
00425                 if( ap->a_onehit != 0 && BU_LIST_NON_EMPTY( &(waiting_segs.l) ) )  {
00426                         int     done;
00427 
00428                         /* Weave these segments into partition list */
00429                         rt_boolweave( &finished_segs, &waiting_segs, &InitialPart, ap );
00430 
00431                         /* Evaluate regions upto box_end */
00432                         done = rt_boolfinal( &InitialPart, &FinalPart,
00433                                 last_bool_start, ss.box_end, regionbits, ap, solidbits );
00434                         last_bool_start = ss.box_end;
00435 
00436                         /* See if enough partitions have been acquired */
00437                         if( done > 0 )  goto hitit;
00438                 }
00439 
00440                 if( ap->a_ray_length > 0.0 && ss.box_end >= ap->a_ray_length )
00441                         goto weave;
00442 
00443                 /* Push ray onwards to next box */
00444                 ss.box_start = ss.box_end;
00445         }
00446 
00447         /*
00448          *  Ray has finally left known space --
00449          *  Weave any remaining segments into the partition list.
00450          */
00451 weave:
00452         if( RT_G_DEBUG&DEBUG_ADVANCE )
00453                 bu_log( "rt_shootray_bundle: ray has left known space\n" );
00454 
00455         if( BU_LIST_NON_EMPTY( &(waiting_segs.l) ) )  {
00456                 rt_boolweave( &finished_segs, &waiting_segs, &InitialPart, ap );
00457         }
00458 
00459         /* finished_segs chain now has all segments hit by this ray */
00460         if( BU_LIST_IS_EMPTY( &(finished_segs.l) ) )  {
00461                 ap->a_return = ap->a_miss( ap );
00462                 status = "MISS prims";
00463                 goto out;
00464         }
00465 
00466         /*
00467          *  All intersections of the ray with the model have
00468          *  been computed.  Evaluate the boolean trees over each partition.
00469          */
00470         (void)rt_boolfinal( &InitialPart, &FinalPart, BACKING_DIST,
00471                 INFINITY,
00472                 regionbits, ap, solidbits);
00473 
00474         if( FinalPart.pt_forw == &FinalPart )  {
00475                 ap->a_return = ap->a_miss( ap );
00476                 status = "MISS bool";
00477                 RT_FREE_PT_LIST( &InitialPart, resp );
00478                 RT_FREE_SEG_LIST( &finished_segs, resp );
00479                 goto out;
00480         }
00481 
00482         /*
00483          *  Ray/model intersections exist.  Pass the list to the
00484          *  user's a_hit() routine.  Note that only the hit_dist
00485          *  elements of pt_inhit and pt_outhit have been computed yet.
00486          *  To compute both hit_point and hit_normal, use the
00487          *
00488          *      RT_HIT_NORM( hitp, stp, rayp )
00489          *
00490          *  macro.  To compute just hit_point, use
00491          *
00492          *  VJOIN1( hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir );
00493          */
00494 hitit:
00495         if(debug_shoot)  rt_pr_partitions(rtip,&FinalPart,"a_hit()");
00496 
00497         /*
00498          *  Before recursing, release storage for unused Initial partitions.
00499          *  finished_segs can not be released yet, because FinalPart
00500          *  partitions will point to hits in those segments.
00501          */
00502         RT_FREE_PT_LIST( &InitialPart, resp );
00503 
00504         /*
00505          *  finished_segs is only used by special hit routines
00506          *  which don't follow the traditional solid modeling paradigm.
00507          */
00508         if(RT_G_DEBUG&DEBUG_ALLHITS) rt_pr_partitions(rtip,&FinalPart,"Parition list passed to a_hit() routine");
00509         ap->a_return = ap->a_hit( ap, &FinalPart, &finished_segs );
00510         status = "HIT";
00511 
00512         RT_FREE_SEG_LIST( &finished_segs, resp );
00513         RT_FREE_PT_LIST( &FinalPart, resp );
00514 
00515         /*
00516          * Processing of this ray is complete.
00517          */
00518 out:
00519         /*  Return dynamic resources to their freelists.  */
00520         BU_CK_BITV(solidbits);
00521         BU_LIST_APPEND( &resp->re_solid_bitv, &solidbits->l );
00522         BU_CK_PTBL(regionbits);
00523         BU_LIST_APPEND( &resp->re_region_ptbl, &regionbits->l );
00524 
00525         /*
00526          *  Record essential statistics in per-processor data structure.
00527          */
00528         resp->re_nshootray++;
00529 
00530         /* Terminate any logging */
00531         if(RT_G_DEBUG&(DEBUG_ALLRAYS|DEBUG_SHOOT|DEBUG_PARTITION|DEBUG_ALLHITS))  {
00532                 bu_log_indent_delta(-2);
00533                 bu_log("----------shootray_bundle cpu=%d  %d,%d lvl=%d (%s) %s ret=%d\n",
00534                         resp->re_cpu,
00535                         ap->a_x, ap->a_y,
00536                         ap->a_level,
00537                         ap->a_purpose != (char *)0 ? ap->a_purpose : "?",
00538                         status, ap->a_return);
00539         }
00540         return( ap->a_return );
00541 }
00542 
00543 /*
00544  * Local Variables:
00545  * mode: C
00546  * tab-width: 8
00547  * c-basic-offset: 4
00548  * indent-tabs-mode: t
00549  * End:
00550  * ex: shiftwidth=4 tabstop=8
00551  */

Generated on Mon Sep 18 01:24:48 2006 for BRL-CAD by  doxygen 1.4.6